【剑指offer】18.二叉搜索树的最近公共祖先
总目录:
1.问题描述
给定一个二叉搜索树, 找到该树中两个指定节点的最近公共祖先。
1.对于该题的最近的公共祖先定义:对于有根树T的两个节点p、q,最近公共祖先LCA(T,p,q)表示一个节点x,满足x是p和q的祖先且x的深度尽可能大。在这里,一个节点也可以是它自己的祖先.
2.二叉搜索树是若它的左子树不空,则左子树上所有节点的值均小于它的根节点的值; 若它的右子树不空,则右子树上所有节点的值均大于它的根节点的值
3.所有节点的值都是唯一的。
4.p、q 为不同节点且均存在于给定的二叉搜索树中。
数据范围:
3<=节点总数<=10000
0<=节点值<=10000
2.问题分析
1迭代,需要用上节点值的有序性,确定找到目标节点的路径,然后从头开始对比两条路径,找到最后一个共同点;
2递归,需要用上节点值的有序性,从根节点开始递归直到找到将两个目标值节点分流为左右两侧的节点;
3.代码实例
迭代
1 /** 2 * struct TreeNode { 3 * int val; 4 * struct TreeNode *left; 5 * struct TreeNode *right; 6 * TreeNode(int x) : val(x), left(nullptr), right(nullptr) {} 7 * }; 8 */ 9 class Solution { 10 public: 11 /** 12 * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可 13 * 14 * 15 * @param root TreeNode类 16 * @param p int整型 17 * @param q int整型 18 * @return int整型 19 */ 20 vector<int> getPath(TreeNode* root, int tgtVal) { 21 vector<int> vec; 22 TreeNode* pCur = root; 23 24 //深度搜索 25 while (pCur != NULL) { 26 //存储当前点 27 vec.push_back(pCur->val); 28 29 //如果当前点即为目标点,则中止搜索 30 if (pCur->val == tgtVal) { 31 break; 32 } 33 34 //根据当前点与目标值的大小比较决定取左还是右 35 if (pCur->val > tgtVal) { 36 pCur = pCur->left; 37 } else { 38 pCur = pCur->right; 39 } 40 } 41 42 return vec; 43 } 44 int lowestCommonAncestor(TreeNode* root, int p, int q) { 45 int tgtNodeVal = -1; 46 47 vector<int> pathP = getPath(root, p); 48 vector<int> pathQ = getPath(root, q); 49 50 //从根节点开始遍历两条路径,直到发现不同点,取最后一个相同点 51 for (int i = 0; i < pathP.size() && i < pathQ.size(); i++) { 52 if (pathP[i] != pathQ[i]) { 53 break; 54 } 55 56 //记录当前相同点 57 tgtNodeVal = pathP[i]; 58 } 59 60 return tgtNodeVal; 61 } 62 };
迭代得直接些
1 /** 2 * struct TreeNode { 3 * int val; 4 * struct TreeNode *left; 5 * struct TreeNode *right; 6 * TreeNode(int x) : val(x), left(nullptr), right(nullptr) {} 7 * }; 8 */ 9 class Solution { 10 public: 11 /** 12 * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可 13 * 14 * 15 * @param root TreeNode类 16 * @param p int整型 17 * @param q int整型 18 * @return int整型 19 */ 20 int lowestCommonAncestor(TreeNode* root, int p, int q) { 21 int tgtNodeVal = -1; 22 TreeNode* pCur = root; 23 24 while (pCur) { 25 if (pCur->val > p && pCur->val > q) { 26 pCur = pCur->left; 27 continue; 28 } 29 if (pCur->val < p && pCur->val < q) { 30 pCur = pCur->right; 31 continue; 32 } 33 tgtNodeVal=pCur->val; 34 break; 35 } 36 37 return tgtNodeVal; 38 } 39 };
递归
1 /** 2 * struct TreeNode { 3 * int val; 4 * struct TreeNode *left; 5 * struct TreeNode *right; 6 * TreeNode(int x) : val(x), left(nullptr), right(nullptr) {} 7 * }; 8 */ 9 class Solution { 10 public: 11 /** 12 * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可 13 * 14 * 15 * @param root TreeNode类 16 * @param p int整型 17 * @param q int整型 18 * @return int整型 19 */ 20 int deltaRP; 21 int deltaRQ; 22 int lowestCommonAncestor(TreeNode* root, int p, int q) { 23 int tgtNodeVal = -1; 24 int deltaRP = root->val - p; 25 int deltaRQ = root->val - q; 26 27 //停止条件 28 if (deltaRP * deltaRQ <= 0) { 29 return root->val; 30 } 31 32 //根据差值符号选择左右方向 33 root = deltaRP > 0 ? root->left : root->right; 34 35 return lowestCommonAncestor(root,p,q); 36 } 37 };