看剑指Offer书上的解法,照葫芦画瓢写的程序,一开始运行出错,改了ans=*it1的顺序运行结果正确,但是提交后有case不通过:(代码的思路并没有完全理解)
经过第一次试用LeetCode在线调试工具,打印中间变量找到问题所在:搜索路径没有把目标节点本身加入进去。
class Solution {
public:
TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
if(!root || !p || !q) return nullptr;
vector<TreeNode*> vp, vq;
findTargetNode(root, p, vp); vp.push_back(p);
findTargetNode(root, q, vq); vq.push_back(q);
/*
vector<TreeNode*>::iterator it = vp.begin();
while(it!=vp.end()) {
cout<<(*it)->val<<endl;
it++;
}
vector<TreeNode*>::iterator it2 = vq.begin();
while(it2!=vq.end()) {
cout<<(*it2)->val<<endl;
it2++;
}
*/
return findMaxCommom(vp, vq);
}
bool findTargetNode(TreeNode* root, TreeNode* p, vector<TreeNode*>& path) {
if(root == nullptr) return false;
if(root == p) return true;
path.push_back(root);
bool found = false;
if(!found && root->left) found = findTargetNode(root->left, p, path);
if(!found && root->right) found = findTargetNode(root->right, p, path);
if(!found) path.pop_back();
return found;
}
TreeNode* findMaxCommom(vector<TreeNode*> vp, vector<TreeNode*> vq) {
vector<TreeNode*>::iterator it1 = vp.begin();
vector<TreeNode*>::iterator it2 = vq.begin();
TreeNode* ans = nullptr;
while(it1!=vp.end() && it2!=vq.end() && *it1==*it2) {
ans=*it1; it1++; it2++;
}
return ans;
}
};
题解区非常简洁优美的递归解法:
两个节点p,q分为两种情况:
p和q在相同子树中
p和q在不同子树中
从根节点遍历,递归向左右子树查询节点信息
递归终止条件:如果当前节点为空或等于p或q,则返回当前节点
递归遍历左右子树,如果左右子树查到节点都不为空,则表明p和q分别在左右子树中,因此,当前节点即为最近公共祖先;
如果左右子树其中一个不为空,则返回非空节点。
(从递归回退的角度去考虑,更容易理解)
class Solution {
public:
TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
if(!root || root==p || root==q)
return root;
TreeNode* left = lowestCommonAncestor(root->left, p, q);
TreeNode* right= lowestCommonAncestor(root->right, p, q);
if(left && right) {
return root;
}
return left? left:right;
}
};