最近公共祖先 LCA 遞歸非遞歸

給定一棵二叉樹,找到兩個節點的最近公共父節點(LCA)。
最近公共祖先是兩個節點的公共的祖先節點且具備最大深度。
假設給出的兩個節點都在樹中存在。node

dfs遞歸寫法數組

查找兩個node的最近公共祖先,分三種狀況:this

  1. 若是兩個node在root的兩邊,那麼最近公共祖先就是root。
  2. 若是兩個node在root的左邊,那麼把root的左子樹做爲root,再遞歸。
  3. 若是兩個node在root的右邊,那麼把root的右子樹做爲root,再遞歸。

深度優先遍歷二叉樹,一旦找到了兩個節點其中的一個,就將這個幾點返回給上一層,上一層節點經過判斷其左右子樹中是否剛好包含n1和n2兩個節點,若是找到,對應的上一層節點確定是所求的LCA;若果不是,將包括兩個節點中任意一個的較低的節點返回給上一層,不然返回NULL。spa

 1 /**
 2  * Definition of TreeNode:
 3  * class TreeNode {
 4  * public:
 5  *     int val;
 6  *     TreeNode *left, *right;
 7  *     TreeNode(int val) {
 8  *         this->val = val;
 9  *         this->left = this->right = NULL;
10  *     }
11  * }
12  */
13 
14 
15 class Solution {
16 public:
17     /*
18      * @param root: The root of the binary search tree.
19      * @param A: A TreeNode in a Binary.
20      * @param B: A TreeNode in a Binary.
21      * @return: Return the least common ancestor(LCA) of the two nodes.
22      */
23     TreeNode * lowestCommonAncestor(TreeNode * root, TreeNode * A, TreeNode * B) {
24         // write your code here
25         //若是當前節點爲空,或者與目標節點中的一個相同,則返回該節點
26         if(root == NULL)    return NULL;
27         if(root==A || root==B)  return root;
28         
29         //遞歸尋找A B在左右子樹的位置
30         TreeNode* left = lowestCommonAncestor(root->left,A,B);
31         TreeNode* right = lowestCommonAncestor(root->right,A,B);
32         
33         //若是A B分別位於root的兩側,則root是他們的LCA,不然是左子樹或者右子樹
34         if(left&&right) return root;
35         
36         return left?left:right;
37         
38         
39     }
40 };

非遞歸:code

後序遍歷非遞歸blog

 1 TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
 2     if (root == nullptr)
 3         return root;
 4     stack<TreeNode*> s;
 5     vector<TreeNode*> vec; // p和q的公共祖先
 6     bool tag1 = false; // true:找到p
 7     bool tag2 = false; // true:找到q
 8     s.push(root);
 9     TreeNode* lastRoot = root;
10     while (!s.empty()) // lastRoot(區分從左/右孩子返回)
11     {
12         root = s.top();
13         if (root == p) {
14             if(tag1 == false && tag2 == false)
15                 vec.push_back(root);
16             tag1 = true;
17         }
18         else if (root == q) {
19             if (tag2 == false && tag1 == false)
20                 vec.push_back(root);
21             tag2 = true;
22         }
23         if (!tag1 && !tag2)
24             vec.push_back(root); // 公共祖先入vector
25         // 找到p,q而且root在公共祖先數組中
26         if (tag1 && tag2 && find(vec.begin(), vec.end(), root) != vec.end())
27             return root;
28         // root的孩子節點還沒訪問
29         if (lastRoot != root->right)
30         {
31             if (lastRoot != root->left) {
32                 if (root->left != nullptr) {
33                     s.push(root->left);
34                     continue;
35                 }
36             }
37             if (root->right != nullptr) {
38                 s.push(root->right);
39                 continue;
40             }
41         }
42         // 孩子節點訪問完,彈棧向上回溯
43         lastRoot = root;
44         s.pop();
45     }
46     return nullptr;
47 }
相關文章
相關標籤/搜索