赞
踩
公共祖先解决。二叉树和二叉搜索树条件下的最近公共祖先。
二叉树篇继续。
给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。
百度百科中最近公共祖先的定义为:“对于有根树 T 的两个节点 p、q,最近公共祖先表示为一个节点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”
示例 1:
输入:root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 1
输出:3
解释:节点 5 和节点 1 的最近公共祖先是节点 3 。
示例 2:
输入:root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 4
输出:5
解释:节点 5 和节点 4 的最近公共祖先是节点 5 。因为根据定义最近公共祖先节点可以为节点本身。
示例 3:
输入:root = [1,2], p = 1, q = 2
输出:1
提示:
树中节点数目在范围 [2, 10^5] 内。
-10^9 <= Node.val <= 10^9
所有 Node.val 互不相同 。
p != q
p 和 q 均存在于给定的二叉树中。
如果左子树有p,右子树有q;左子树有q,右子树有p。此时返回中间节点(最近公共祖先)。
如果一边子树为空,另一边子树有p或q之一。此时返回left或者right,即子树返回的节点。注意:这里不能返回中间节点。会把最近公共祖先丢掉。
如果两边子树都为空,说明该中间节点的左右子树不包含p和q。向上返回空。
class Solution { public: TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) { if(!root) return nullptr; if(root->val == q->val || root->val == p->val) return root; //左 TreeNode* left = lowestCommonAncestor(root->left,p,q); //右 TreeNode* right = lowestCommonAncestor(root->right,p,q); //中节点 if(!left && !right) return nullptr;//说明该子树没有p也没有q else if(!left && right) return right;//一定要返回right。而不是root else if(!right && left) return left;//一定要返回left。而不是root。 else return root; } };
补充思路中没提及的情况2:自身是祖先——以上代码在哪一处包含
拯救:没想到终止条件2时
class Solution { public: TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) { if(!root) return nullptr; //没想到在这里直接终止。 //if(root->val == q->val || root->val == p->val) return root; //左 TreeNode* left = lowestCommonAncestor(root->left,p,q); //右 TreeNode* right = lowestCommonAncestor(root->right,p,q); //中节点 if(root->val == p->val || root->val == q->val){ return root; }else{ if(!left && !right) return nullptr;//说明该子树没有p也没有q else if(!left && right) return right;//一定要返回right。而不是root else if(!right && left) return left;//一定要返回left。而不是root。 else return root; } } };
理解提示给节点值不重复、p和q不相等、p 和 q 均存在于给定的二叉树中
给定一个二叉搜索树, 找到该树中两个指定节点的最近公共祖先。
百度百科中最近公共祖先的定义为:“对于有根树 T 的两个结点 p、q,最近公共祖先表示为一个结点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”
例如,给定如下二叉搜索树: root = [6,2,8,0,4,7,9,null,null,3,5]
示例 1:
输入: root = [6,2,8,0,4,7,9,null,null,3,5], p = 2, q = 8
输出: 6
解释: 节点 2 和节点 8 的最近公共祖先是 6。
示例 2:
输入: root = [6,2,8,0,4,7,9,null,null,3,5], p = 2, q = 4
输出: 2
解释: 节点 2 和节点 4 的最近公共祖先是 2, 因为根据定义最近公共祖先节点可以为节点本身。
说明:
所有节点的值都是唯一的。
p、q 为不同节点且均存在于给定的二叉搜索树中。
如果当作普通二叉树,那么上一道题肯定能解决。那么此处就要利用二叉搜索树的性质。
/** * Definition for a binary tree node. * struct TreeNode { * int val; * TreeNode *left; * TreeNode *right; * TreeNode(int x) : val(x), left(NULL), right(NULL) {} * }; */ class Solution { public: void swap(TreeNode*& p, TreeNode*& q){ if(p->val > q->val){//设定q的值大于p的值。 TreeNode* temp = p; p = q; q = temp; } return; } TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) { //先保证p的值小于q的值 swap(p,q); //终止条件1:空节点返回空 if(!root) return nullptr; //终止条件2:中间节点的值在p和q中间,或自身祖先。 if( (p->val < root->val && root->val < q->val) || root->val == p->val || root->val == q->val) return root; if(root->val > q->val){ TreeNode* left = lowestCommonAncestor(root->left,p,q);//进到左子树 return left;//此处会直接返回。没有遍历整个树。 }else if(root->val < p->val){ TreeNode* right = lowestCommonAncestor(root->right,p,q);//进到右子树 return right; } return nullptr;//走不到这。 } };
class Solution { public: TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) { //终止条件:空节点返回空 if(!root) return nullptr; if(root->val > q->val && root->val > p->val){ TreeNode* left = lowestCommonAncestor(root->left,p,q);//进到左子树 //没有加left为空的判断,因为题目说p和q存在。严格来说加上更通用。 if(left) return left;//此处会直接返回。没有遍历整个树。 }else if(root->val < p->val && root-=>val < q->val){ TreeNode* right = lowestCommonAncestor(root->right,p,q);//进到右子树 if(right) return right; } //中 return root;//剩余情况。 } };
class Solution { public: TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) { queue<TreeNode*> que; if(!root) return nullptr; que.push(root); while(!que.empty()){ TreeNode* cur = que.front();que.pop(); if(cur->val > p->val && cur->val > q->val && cur->left){ que.push(cur->left); }else if(cur->val < p->val && cur->val < q->val && cur->right){ que.push(cur->right); }else return cur; } return nullptr;//能找到在上一行会直接return,不会走到这一行。 } };
对比参考代码:上面还是有点复杂——用了队列,不过这是迭代模版,肯定能实现。
参考给出:直接用root指针交接下一棒。
(欢迎指正,转载标明出处)
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。