BST的最近公共祖先
利用BST的顺序特性: 如果当前根节点比p和q大, 公共祖先一定在左子树
如果当前根节点比p和q小, 公共祖先一定在右子树
如果节点在pq之间, 就说明一个在左子树, 一个在右子数, 所以就是最近的公共祖先
(这里也不涉及到遍历, 只需要一个左一个右就行了)
class Solution {
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
//有个小细节,root,p,q都是节点,所以要用val
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;
}
}
BST中的插入操作
Trick: 插入任何一个节点都可以在叶子节点找到
if(root == null)就说明找到叶子节点了
迭代法: 这里连接的逻辑就是, 当root==null时,说明需要连接了,根据递归函数变成,root.left = node
class Solution {
public TreeNode insertIntoBST(TreeNode root, int val) {
//确定终止条件, 就是找到叶子节点
if(root == null){
//所以就要创建一个新节点
TreeNode node = new TreeNode(val);
return node;
}
//如果小于就是左边, 传入的是root
if(val < root.val){
root.left = insertIntoBST(root.left, val);
} else {
root.right = insertIntoBST(root.right, val);
}
return root;
}
}
删除BST中的节点
五种情况:
- 没找到要删除的节点
- 删的是叶子节点
- 左不空, 右为空
- 左为空, 右不空
- 左右都不为空
这里第五种情况, 让右孩子继位, 那么就让左子树放在右子树的左孩子位置(如图)
删除条件就在终止条件里,所以会比较复杂
仔细体会每个条件下return的值, 这个是很妙的
- 定义一个cur = root.right, 定位到右子树头
- 因为要把左子树加到右子树, 所以要移动cur到右子树的最左
- 然后cur.left = root.left (移动左子树)
- 直接return root.right就行
(注意这里没有找到是root==null; 还有别忘记最后写递归了😓)
class Solution {
public TreeNode deleteNode(TreeNode root, int key) {
//写终止条件, 有五种情况
//如果没有找到
if(root == null){
return null;
}
//如果找到了
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.left == null && root.right != null){
return root.right;
} else {
//第五种情况:
TreeNode cur = root.right;
//第一步让cur定位到最左边
while(cur.left != null){
cur = cur.left;
}
//第二步,让cur指向左子树
cur.left = root.left;
//第三步,删除节点,也就是直接return
return root.right;
}
}
//然后开始递归, 这里也要考虑大小和左右
if(key < root.val) {
root.left = deleteNode(root.left, key);
}
if(key > root.val){
root.right = deleteNode(root.right, key);
}
return root;
}
}