力扣-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 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步