树与图中等3 种解法

#235二叉搜索树的最近公共祖先

在二叉搜索树中寻找两个给定节点的最近公共祖先。

#二叉搜索树#深度优先搜索#路径

解题主线

01

若 p、q 同在当前值一侧就继续向该侧走,否则当前节点就是分叉点。

解法 1递归利用 BST

根据两个目标相对根的位置递归进入唯一可能的子树。

时间复杂度

O(h)

空间复杂度

O(h)

235. 二叉搜索树的最近公共祖先 · 递归利用 BST
import java.util.*;

class TreeNode {
    int val;
    TreeNode left;
    TreeNode right;

    TreeNode(int val) {
        this.val = val;
    }
}

class Solution {
    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
        if (root == null) return null;
        if (p.val < root.val && q.val < root.val) {
            return lowestCommonAncestor(root.left, p, q);
        }
        if (p.val > root.val && q.val > root.val) {
            return lowestCommonAncestor(root.right, p, q);
        }
        return root;
    }
}

根据两个目标相对根的位置递归进入唯一可能的子树。

解法 2迭代寻找分叉点

沿 BST 单路径移动,直到两个目标位于两侧或命中当前节点。

时间复杂度

O(h)

空间复杂度

O(1)

235. 二叉搜索树的最近公共祖先 · 迭代寻找分叉点
import java.util.*;

class TreeNode {
    int val;
    TreeNode left;
    TreeNode right;

    TreeNode(int val) {
        this.val = val;
    }
}

class Solution {
    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
        TreeNode current = root;
        while (current != null) {
            if (p.val < current.val && q.val < current.val) current = current.left;
            else if (p.val > current.val && q.val > current.val) current = current.right;
            else return current;
        }
        return null;
    }
}

沿 BST 单路径移动,直到两个目标位于两侧或命中当前节点。

解法 3比较根到节点路径

分别生成根到 p、q 的路径,最后一个相同节点即最近公共祖先。

时间复杂度

O(h)

空间复杂度

O(h)

235. 二叉搜索树的最近公共祖先 · 比较根到节点路径
import java.util.*;

class TreeNode {
    int val;
    TreeNode left;
    TreeNode right;

    TreeNode(int val) {
        this.val = val;
    }
}

class Solution {
    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
        List<TreeNode> first = pathTo(root, p);
        List<TreeNode> second = pathTo(root, q);
        TreeNode answer = null;
        for (int i = 0; i < Math.min(first.size(), second.size()); i++) {
            if (first.get(i) != second.get(i)) break;
            answer = first.get(i);
        }
        return answer;
    }

    private List<TreeNode> pathTo(TreeNode root, TreeNode target) {
        List<TreeNode> path = new ArrayList<>();
        TreeNode current = root;
        while (current != null) {
            path.add(current);
            if (current == target) break;
            current = target.val < current.val ? current.left : current.right;
        }
        return path;
    }
}

分别生成根到 p、q 的路径,最后一个相同节点即最近公共祖先。

边界与易错点

  • 比较的是 p、q 的值与当前节点值,不是只比较 p 和 q。
  • 组合文件与独立文件的重复递归、迭代实现需合并。
整理来源

由旧仓库源码复核、去重并整理;展示代码已按 Java 21 语义修正明显问题。

leetcode/src/main/java/tree/Q235_236_lowestCommonAncestor.javaleetcode/src/main/java/tree/Q235_bst_lowestCommonAncestor.java