搜索二叉树保存路径法

  • 保存路径找出最近公共祖先。
  • 找出公共祖先,临界情况分为,第一个不同点,p点,q点。
  • 递归函数是if-elseif-else结构,不需要显式return,返回正序顺序,所以先push_back再递归。
#include <vector>
class Solution {
public:
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 
     * @param root TreeNode类 
     * @param p int整型 
     * @param q int整型 
     * @return int整型
     */
    void getPath(vector<int>& v,int value,TreeNode* root)
    {

        if(root->val==value)
        {
            v.push_back(root->val);
            return;
        }
        else if(root->val<value)
        {
            v.push_back(root->val);
            getPath(v,value,root->right);
        }
        else{
            v.push_back(root->val);
            getPath(v,value,root->left);
        }   
    }
    int lowestCommonAncestor(TreeNode* root, int p, int q) {
        // write code here
        if(!root)
        {
            return -1;
        }
        vector<int> p1;
        vector<int>p2;
        getPath(p1, p,root);
        getPath(p2, q,root);
        for(int i=0;i<min(p1.size(),p2.size());i++)
        {
            if(p1[i]!=p2[i])
            {
                return p1[i-1];
            }
        }
        return p1.size()>p2.size()?p2[p2.size()-1]:p1[p1.size()-1];
    }
};

二叉树通用法保存路径

  • 非搜索二叉树也适用,上一种方法比,要注意弹出元素,用栈模拟。
  • 两个栈只再递归的某一段过程改变,在找到目标元素时,不再更新,因此用引用/全局变量实现避免栈全阶段变化。
  • 更通用的方法,但是没有结合搜索二叉树的特点。
/**
 * struct TreeNode {
 *  int val;
 *  struct TreeNode *left;
 *  struct TreeNode *right;
 *  TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 * };
 */
class Solution {
  public:
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     *
     * @param root TreeNode类
     * @param p int整型
     * @param q int整型
     * @return int整型
     */
    void recrusion(TreeNode* root, int p, int q, stack<int>& sp, stack<int>& sq) {
        if (!root) {
            return;
        }
        if (sp.empty() || sp.top() != p) {
            sp.push(root->val);
        }
        if (sq.empty() || sq.top() != q) {
            sq.push(root->val);
        }

        recrusion(root->left, p, q, sp, sq);
        recrusion(root->right, p, q, sp, sq);
        if (sp.top() != p) {
            sp.pop();
        }
        if (sq.top() != q) {
            sq.pop();
        }
    }
    int lowestCommonAncestor(TreeNode* root, int p, int q) {
        // write code here
        //保存路径
        stack<int> sp;
        stack<int> sq;
        recrusion(root, p, q, sp, sq);
        while (sp.size() > sq.size()) {
            sp.pop();
        }
        while (sp.size() < sq.size()) {
            sq.pop();
        }
        while (sp.top() != sq.top()) {
            sp.pop();
            sq.pop();
        }
        return sp.top();
    }
};

递归法

  • 搜索二叉树保证搜索过程是单向的不需要回溯,由上往下。
  • 临界分成三种,该节点属于两个节点之一和该节点为p,q的父节点。
  • 当根节点不是,则转为从左树节点开始寻找以及从右子树节点开始寻找。
  • 向上返回节点值。
int lowestCommonAncestor(TreeNode* root, int p, int q) {
        // write code here
        if(!root)
        {
            //找不到
            return -1;
        }
        if(root->val==p||root->val==q||(root->val<max(p,q)&&root->val>min(p,q)))
        {
            return root->val;
        }
        else if(root->val>max(p,q))
        {

            return lowestCommonAncestor(root->left, p, q);
        }
        else{
            return lowestCommonAncestor(root->right, p, q);
        }
    }