日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

leetcode 236. 二叉树的最近公共祖先 思考分析

發布時間:2023/12/1 编程问答 24 豆豆
生活随笔 收集整理的這篇文章主要介紹了 leetcode 236. 二叉树的最近公共祖先 思考分析 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

目錄

    • 題目
    • 思考分析
    • 改進

本文章代碼思路來源于公眾號【代碼隨想錄】

題目

給定一個二叉樹, 找到該樹中兩個指定節點的最近公共祖先。

百度百科中最近公共祖先的定義為:“對于有根樹 T 的兩個結點 p、q,最近公共祖先表示為一個結點 x,滿足 x 是 p、q 的祖先且 x
的深度盡可能大(一個節點也可以是它自己的祖先)。”

思考分析

1、自下而上遍歷對于此題有極大幫助,而后序遍歷的特征便是優先處理葉子結點
2、如何判斷一個節點是結點q和結點p的公共祖先:
如果找到一個結點,左子樹出現結點p,右子樹出現結點q,或者左子樹出現結點q,右子樹出現結點p。
確定返回值和參數
如果單純只是告訴我們是否找到結點q或者p,那么返回值為bool就行了。
但是我們還要返回最近公共結點,所以返回值為TreeNode* 類型,如果遇到p或者q,就把p或者q返回,返回值不為空就說明了找到了q或者p。

TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q)

確定終止條件
如果找到結點p或者結點q或者結點為空,返回

if(root == q || root == p || root == NULL) return root;

確定單層邏輯
首先確定一點我們需要遍歷樹的所有結點。
直觀上講,如果找到了最近公共祖先,直接一路返回就可以了。如下圖

但是事實上還要遍歷根結點的右子樹(即使現在已經找到了目標結點),這是因為在后序遍歷中,如果想要利用left和right做邏輯處理,不能立即返回,而是要等到left和right的邏輯處理完之后才能返回。

left = 遞歸函數(root->left); right = 遞歸函數(root->right); left 和 right 的邏輯處理

所以我們要遍歷整棵樹。

TreeNode* left = lowestCommonAncestor(root->left,p,q); TreeNode* right= lowestCommonAncestor(root->right,p,q);

1、如果left和right都不為空,說明此時root就是最近公共祖先。
2、如果left為空,right不為空,就返回right,說明目標結點是通過right返回的,反之依然。

3、如果left和right都為空,則返回left或者right都是可以的,也就是返回空。

if(left == NULL && right != NULL) return right; else if(left != NULL && right ==NULL) return left; else return NULL; //此時只有left和right同時為空

整個遍歷思路:

/*** Definition for a binary tree node.* struct TreeNode {* int val;* TreeNode *left;* TreeNode *right;* TreeNode(int x) : val(x), left(NULL), right(NULL) {}* };*///如果一個結點不是另外一個結點的祖先,那么他們的最近祖先的深度一定是深度最小結點的深度-1//如果一個結點是另外一個結點的祖先,那么最近祖先就是是祖先的那個結點。 class Solution { public:TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {if(root == q || root == p || root == NULL ) return root;TreeNode* left = lowestCommonAncestor(root->left,p,q);TreeNode* right = lowestCommonAncestor(root->right,p,q);if(left != NULL && right != NULL) return root;else if(left == NULL && right != NULL) return right;else if(left != NULL && right ==NULL) return left;else return NULL; //此時只有left和right同時為空} };

改進

在遍歷完左子樹之后,若是返回的left不是NULL,也不是p和q,則說明在左子樹中已經找到了公共祖先了,此時可以直接返回left的值,無需再遍歷右子樹。這就是剪枝操作。

/*** Definition for a binary tree node.* struct TreeNode {* int val;* TreeNode *left;* TreeNode *right;* TreeNode(int x) : val(x), left(NULL), right(NULL) {}* };*///如果一個結點不是另外一個結點的祖先,那么他們的最近祖先的深度一定是深度最小結點的深度-1//如果一個結點是另外一個結點的祖先,那么最近祖先就是是祖先的那個結點。 class Solution { public:TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {if(root == q || root == p || root == NULL ) return root;TreeNode* left = lowestCommonAncestor(root->left,p,q);//*****************剪枝操作******************if(left !=NULL && left !=p && left != q) return left; //*******************************************TreeNode* right = lowestCommonAncestor(root->right,p,q);if(left != NULL && right != NULL) return root;else if(left == NULL && right != NULL) return right;else if(left != NULL && right ==NULL) return left;else return NULL; //此時只有left和right同時為空} };

加入打印信息,對遍歷的過程更加了解熟悉;

class Solution { public:TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {if(root == NULL) cout<<"NULL"<<endl;else cout<<root->val<<endl;if(root == q || root == p || root == NULL ) return root;TreeNode* left = lowestCommonAncestor(root->left,p,q);//*****************剪枝操作******************if(left !=NULL && left !=p && left != q) return left; //*******************************************TreeNode* right = lowestCommonAncestor(root->right,p,q);if(left != NULL && right != NULL) return root;else if(left == NULL && right != NULL) return right;else if(left != NULL && right ==NULL) return left;else return NULL; //此時只有left和right同時為空} };

這一題感覺之后還需要多看幾遍,多體會體會,感覺有些地方還是沒理解。
若是有新的理解,再更新。

總結

以上是生活随笔為你收集整理的leetcode 236. 二叉树的最近公共祖先 思考分析的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。