方法一:DFS、路径比较

1、利用深度优先搜索分别获取两个结点在二叉树中的路径;

2、比较两个路径,得到最后相同的的结点即为两个结点的最近公共祖先。

时间复杂度:o(n)。最坏情况需要遍历二叉树所有节点

空间复杂度:o(n)。

class Solution {
  public:
    bool flag = false;
    //深度优先搜索(dfs)
    void dfs(TreeNode* root, vector<int>& path, int target) {
        if (root == nullptr || flag == true)
            return;

        path.push_back(root->val);
        if (root->val == target) {
            flag = true;
            return;
        }
        dfs(root->left, path, target);
        dfs(root->right, path, target);

        if (flag == true)
            return;
        //如果到达底部还未找到,回溯
        path.pop_back();
    }

    int lowestCommonAncestor(TreeNode* root, int o1, int o2) {
        vector<int> path1;
        vector<int> path2;

        dfs(root, path1, o1);
        //重置flag寻找下一个
        flag = false;
        dfs(root, path2, o2);

        int num;
        //寻找最后一个相同的结点
        for (int i = 0; i < path1.size() && i < path2.size(); i++) {
            if (path1[i] == path2[i])
                num = path1[i];
        }

        return num;
    }
};

方法二:递归

  • step 1:如果o1和o2中的任一个和root匹配,那么root就是最近公共祖先。
  • step 2:如果都不匹配,则分别递归左、右子树。
  • step 3:如果有一个节点出现在左子树,并且另一个节点出现在右子树,则root就是最近公共祖先.
  • step 4:如果两个节点都出现在左子树,则说明最低公共祖先在左子树中,否则在右子树。
  • step 5:继续递归左、右子树,直到遇到step1或者step3的情况。

时间复杂度:o(n)。

空间复杂度:o(n)。

class Solution {
public:
    int lowestCommonAncestor(TreeNode* root, int o1, int o2) {
        //该子树没找到,返回-1
        if(root == NULL) 
            return -1;
        //该节点是其中某一个节点
        if(root->val == o1 || root->val == o2) 
            return root->val;
        //左子树寻找公共祖先
        int left = lowestCommonAncestor(root->left, o1, o2); 
        //右子树寻找公共祖先
        int right = lowestCommonAncestor(root->right, o1, o2); 
        //左子树为没找到,则在右子树中
        if(left == -1) 
            return right;
        //右子树没找到,则在左子树中
        if(right == -1) 
            return left;
        //否则是当前节点
        return root->val; 
    }
};