0927剑指offer

两个题目都不会,忘记咋做了,啊啊啊。。。

LCR 194. 二叉树的最近公共祖先

题目
方法一:递归
看的答案,思路是用后续遍历进行递归,感觉不太好想就是判断是否是公共节点。

class Solution {
public:
//全局变量用来记录结果
    TreeNode* ans;
    //后续遍历
    bool dfs(TreeNode* root,TreeNode* p,TreeNode*q)
    {
         if(root==NULL)  return false;
         bool lson=dfs(root->left,p,q);
         bool rson=dfs(root->right,p,q);
         if((lson&&rson)||((root->val==p->val)||(root->val==q->val))&&(lson||rson))
         {
             ans=root;
         }
         //看左子树||右子树||是否包含p,q,以及左右子树是p或q
         return lson||rson||(root->val==p->val||root->val==q->val);
    }
    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
        dfs(root,p,q);
        return ans;
       

    }
};

方法二:

LCR 193. 二叉搜索树的最近公共祖先

题目
与上面的不一样的是,二叉搜索树是有顺序的,因此判断左右子树,是通过比较值来进行的。
思路:用两个数组分别记录后续遍历的p,和q的祖先,因为后续遍历的特点就是遍历到该节点师,栈中的节点就是该节点的祖先。之后再同时遍历这两个数组,记录最后一次遇到的相同的节点,就是该祖先。
一个bug: 因为是从上往下到p或者q的,所以path[0]就是root,所以要记录最后的相同的,而不是一遇到相同的就直接return。

class Solution {
public:
    vector<TreeNode*> find(TreeNode* root,TreeNode* k)
    {
        vector<TreeNode*> v;
        TreeNode* l=root;
        while(l!=k)
        {
            v.push_back(l);
            if(l->val==k->val) break;
            else if(l->val>k->val)
            {
                l=l->left;
            }
            else {                
                l=l->right;
            }
        }
        v.push_back(l);
        return v;
    }
    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
        vector<TreeNode*> pathp,pathq;
        TreeNode* res;
        pathp=find(root,p);
        pathq=find(root,q);
        for(int i=0,j=0;i<pathp.size()&&j<pathq.size();i++,j++)
        {
            if(pathp[i]==pathq[j])
                res=pathp[i];
        }
        return res;          
    }
};

一个小bug: 就是遇到p,或者q,也得加入v中,因为可能p是q的祖先,或者q是p的祖先。

 vector<TreeNode*> find(TreeNode* root,TreeNode* k)
    {
        vector<TreeNode*> v;
        TreeNode* l=root;
        while(l)
        {
            if(l->val==k->val) break;
            else if(l->val>k->val)
            {
                v.push_back(l);
                l=l->left;
            }
            else {
                v.push_back(l);
                l=l->right;
            }
        }
      v.push_back(l); ///这里!!!必须加,否则就通过不了样例2,输出的是6不是2。
        return v;
    }
    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
        vector<TreeNode*> pathp,pathq;
        TreeNode* res;
        pathp=find(root,p);
        pathq=find(root,q);
        for(int i=0,j=0;i<pathp.size()&&j<pathq.size();i++,j++)
        {
            if(pathp[i]==pathq[j])
                res=pathp[i];
        }
        return res;          
    }
};

方法二:一次遍历
思路:同时进行比较,不需要花费多余的空间存储p,q的路径。
当node小于p和q时,说明p,q在node的右子树上。
当node大于p和q时,说明p,q在node的左子树上。
否则就是node == p,或者node==q,或者node就是q,p 的公共祖先。

TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
        TreeNode* res,*node=root;
        while(node)
        {
           if(node->val>p->val&&node->val>q->val)
           {
               node=node=node->left;
           } 
           else if(node->val<p->val&&node->val<q->val)
           {
               node=node->right;
           }
           else 
           {
                res=node;
                break;
           }
        }
        return res;          
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值