給定一棵二叉樹,找到兩個節點的最近公共父節點(LCA)。
最近公共祖先是兩個節點的公共的祖先節點且具備最大深度。
假設給出的兩個節點都在樹中存在。node
dfs遞歸寫法數組
查找兩個node的最近公共祖先,分三種狀況:this
深度優先遍歷二叉樹,一旦找到了兩個節點其中的一個,就將這個幾點返回給上一層,上一層節點經過判斷其左右子樹中是否剛好包含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 }