235.二叉搜索树的最近公共祖先
思路:根据二叉搜索树的特性,只需要判断当前节点是否在[p,q]范围内就可以,如果在这个范围里,说明当前节点就是其最近公共祖先。
class Solution {
// 根据二叉搜索树特性,只要当前节点在[p,q]范围内就说明是其最近祖先
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
if (root == null) return null;
if (p.val > q.val) {
// 保证 p.val <= q.val,便于后续情况讨论
return lowestCommonAncestor(root, q, p);
}
if (root.val >= p.val && root.val <= q.val) {
// p <= root <= q
// 即 p 和 q 分别在 root 的左右子树,那么 root 就是 LCA
return root;
}
if (root.val > q.val) {
// p 和 q 都在 root 的左子树,那么 LCA 在左子树
return lowestCommonAncestor(root.left, p, q);
} else {
// p 和 q 都在 root 的右子树,那么 LCA 在右子树
return lowestCommonAncestor(root.right, p, q);
}
}
}
精简版:
class Solution {
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
if (root.val > p.val && root.val > q.val)
return lowestCommonAncestor(root.left, p, q);
if (root.val < p.val && root.val < q.val)
return lowestCommonAncestor(root.right, p, q);
return root;
}
}
701.二叉搜索树中的插入操作
思路:如果要递归地插入或者删除二叉树节点,递归函数一定要有返回值,而且返回值需要被正确的接收。
插入的过程可以分两部分:
1、寻找正确的插入位置,类似 700. 二叉搜索树中的搜索。
2、把元素插进去,这就要把新节点以返回值的方式接到父节点上。
class Solution {
public TreeNode insertIntoBST(TreeNode root, int val) {
// 找到空位置插入新节点
if (root == null) return new TreeNode(val);
// if (root.val == val)
// BST 中一般不会插入已存在元素
if (root.val < val)
root.right = insertIntoBST(root.right, val);
if (root.val > val)
root.left = insertIntoBST(root.left, val);
return root;
}
}
450.删除二叉搜索树中的节点
思路:删除比插入和搜索都要复杂一些,分三种情况:
情况 1:A
恰好是末端节点,两个子节点都为空,那么它可以当场删除;
情况 2:A
只有一个非空子节点,那么它要让这个孩子接替自己的位置;
情况 3:A
有两个子节点,为了不破坏BST
的性质,A
必须找到左子树中最大的那个节点或者右子树中最小的那个节点来接替自己,以下的解法是用右子树中最小节点来替换。
class Solution {
public TreeNode deleteNode(TreeNode root, int key) {
if (root == null) return null;
if (root.val == key) {
// 这两个 if 把情况 1 和 2 都正确处理了
// 左子树为空,直接返回右子树
// 右子树为空,直接返回左子树
// 这里若左右子树均为空,也是返回空
if (root.left == null) return root.right;
if (root.right == null) return root.left;
// 处理情况 3 ,左右子树都不为空
// 获得右子树最小的节点
TreeNode minNode = getMin(root.right);
// 删除右子树最小的节点
root.right = deleteNode(root.right, minNode.val);
// 用右子树最小的节点替换 root 节点
minNode.left = root.left;
minNode.right = root.right;
root = minNode;
} else if (root.val > key) {
root.left = deleteNode(root.left, key);
} else if (root.val < key) {
root.right = deleteNode(root.right, key);
}
return root;
}
TreeNode getMin(TreeNode node) {
// BST 最左边的就是最小的
while (node.left != null) node = node.left;
return node;
}
}