2022-11-09 14:16阅读: 19评论: 0推荐: 0

力扣-236-二叉树的最近公共祖先

一般来说二叉树是向下遍历的,这里要找公共祖先就要向上遍历

考虑到本身也可以是公共祖先的情况…没什么思路

但肯定跟遍历有关,而且或许涉及回溯
要么就需要额外的数据结构保存

好,题解的思路1是后序遍历

这里会不会出现树种有相同的节点?

可以把这个
if (root->val == p->val || root->val == q->val || (leftHas && rightHas)) return true;
写成这个
return (root->val == p->val || root->val == q->val || (leftHas && rightHas));

这是官方的题解思路代码

TreeNode* ans;
// 这个后序遍历方法多了两个参数,要查找的节点p、q
bool backTravel(TreeNode* root,TreeNode* p,TreeNode* q) {
if (!root) return false;
// 但是问题是怎么判断呢?怎么记录包不包含
// 用两个布尔值
bool leftHas = backTravel(root->left,p,q);
bool rightHas = backTravel(root->right,p,q);
// 返回的时机应该放在判断自己并向上返回状态之前
// 因为如果子节点中都满足了
// 返回的条件是1. 子树中已经有这两个目标了2. 子树中能满足一个,加上自己能满足一个就凑够了
// 但是2的前提是不会出现重复元素吧,比如不能两边都有q
if ((leftHas && rightHas) || (root->val == q->val || root->val == p->val) && (leftHas || rightHas))
// 因为是递归,这里不能break
// 那岂不是还会继续往上走?root会被刷新吗?
ans = root;
// 判断节点
// 这里就通过这两个布尔值实现了向上的状态传递
return (root->val == p->val || root->val == q->val || (leftHas && rightHas));
}
TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
// 后续遍历,第一个想法肯定是递归,那迭代怎么写?
backTravel(root, p, q);
return ans;
}

但是有两个很明显的问题,1是它直接比较了节点的val而不是比较节点,这是不合适的,如果有两个val相同但是指针不同的不同节点,会被误判。

比如在某节点的左子树中有两个val相同都满足q的节点,可能就会被误判

另外一点就是,给ans赋值的时候,就算找到了是不是也会继续往上走?是的,但是不会刷新root了,因为如果一颗子树中找齐了,另一个子树是不可能再有的,同时根节点也不可能再有一致的了
但就算如此,不能break看起来仍然有多余的递归步骤

简化这题的不完美但是看起来很简洁的写法可以这么写

// 本质上使用节点指针替代了题解1中的bool变量
// 另外官解1中比较节点的val显然不合适
// 但是仍然存在多余的向上遍历,虽然这个过程中结果指针会向上传递,而且不会被覆盖保证了结果是正确的
TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
if (!root) return nullptr;
TreeNode* leftHas = lowestCommonAncestor(root->left,p,q);
TreeNode* rightHas = lowestCommonAncestor(root->right,p,q);
if ((leftHas && rightHas)||root==p||root==q) return root;
if (leftHas) return leftHas;
else return rightHas;
}

本文作者:YaosGHC

本文链接:https://www.cnblogs.com/yaocy/p/16873353.html

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   YaosGHC  阅读(19)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
💬
评论
📌
收藏
💗
关注
👍
推荐
🚀
回顶
收起