代码随想录算法训练营第二十二天 | 235. 二叉搜索树的最近公共祖先、701.二叉搜索树中的插入操作 、450.删除二叉搜索树中的节点
235. 二叉搜索树的最近公共祖先
递归法
思路:本题不需要考虑遍历顺序,利用 BST 的特性即可求解,递归中不用写与中节点相关的代码。各种情况如下:
- 当前节点的值大于 p 、q,则说明最近公共祖先一定在左子树中;
- 当前节点的值小于 p、 q,则说明最近公共祖先一定在右子树中;
- 当前节点的值位于 p、 q 之间,则说明当前节点就是最近公共祖先(由 BST 特性决定)。
class Solution {
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
if (root == null) return null; // 结束条件
if (root.val > p.val && root.val > q.val) { // 左
TreeNode left = lowestCommonAncestor(root.left, p, q);
if (left != null) return left;
}
if (root.val < p.val && root.val < q.val) { // 右
TreeNode right = lowestCommonAncestor(root.right, p, q);
if (right != null) return right;
}
return root; // 代表当前节点的值位于 p 和 q 中间,当前节点一定是最近公共祖先
}
}
迭代法
思路:见递归法。
class Solution {
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
while (root != null) {
if (root.val > p.val && root.val > q.val) {
root = root.left;
} else if (root.val < p.val && root.val < q.val){
root = root.right;
} else {
return root;
}
}
return null;
}
}
701.二叉搜索树中的插入操作
递归法
思路:本题关键在于理解,对于 BST,插入节点操作仅考虑叶子节点处即可。
class Solution {
public TreeNode insertIntoBST(TreeNode root, int val) {
if (root == null) {
TreeNode newNode = new TreeNode(val);
return newNode;
}
if (val < root.val) {
root.left = insertIntoBST(root.left, val);
}
if (val > root.val) {
root.right = insertIntoBST(root.right, val);
}
return root;
}
}
450.删除二叉搜索树中的节点
递归法
思路:需要考虑以下五种情况:
1、未找到 key 值;
2、key 值位于叶子节点;
3、key 值所在节点,左孩子不为空,右孩子为空;
4、key 值所在节点,右孩子不为空,左孩子为空;
5、key 值所在节点,左右孩子都不为空(最复杂,因为要大幅调整树的结构),可将当前节点的左或右孩子作为替代。以右孩子替代为例,需要将右孩子所代表的子树中,节点值最小的节点,作为原左孩子节点的父节点,如下图所示:
class Solution {
public TreeNode deleteNode(TreeNode root, int key) {
if (root == null) return root; // 情况一
if (root.val == key) {
if (root.left == null && root.right == null) { // 情况二
return null;
} else if (root.left != null && root.right == null) { // 情况三
return root.left;
} else if (root.right != null && root.left == null) { // 情况四
return root.right;
} else { // 情况五
TreeNode temp = root.right;
while (temp.left != null) {
temp = temp.left;
}
temp.left = root.left;
return root.right;
}
}
// 由于是 BST,可以明确递归的方向
if (key < root.val) {
root.left = deleteNode(root.left, key);
}
if (key > root.val) {
root.right = deleteNode(root.right, key);
}
return root;
}
}