235.二叉搜索树的最近公共祖先
利用二叉搜索树的性质
从上到下去遍历,遇到 cur节点是数值在[p, q]区间中则一定可以说明该节点cur就是p 和 q的公共祖先。
问题来了,一定是最近公共祖先吗?
-
如果 从节点5继续向左遍历,那么将错过成为p的祖先, 如果从节点5继续向右遍历则错过成为q的祖先。
所以当我们从上向下去递归遍历,第一次遇到 cur节点是数值在[q, p]区间中,那么cur就是 q和p的最近公共祖先。
递归法:
- 递归函数
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q)
- 终止条件
if(root == null) return null;
- 单层递归逻辑
if(p.val < root.val && q.val < root.val) {
TreeNode left = lowestCommonAncestor(root.left,p,q);
if(left != null) return left;
}
else if(p.val > root.val && q.val > root.val) {
TreeNode right = lowestCommonAncestor(root.right,p,q);
if(right != null) return right;
}
//剩下的情况,cur一定是在p和q之间,找到了结果
return root;
701.二叉搜索树中的插入操作
根据二叉搜索树的特性遍历,遇到空了说明找到了要插入的位置,把节点new出来返回。
怎么接住呢?在下面左右递归的同时接住root.left = traversal(...)
class Solution {
public TreeNode insertIntoBST(TreeNode root, int val) {
if(root == null) {
TreeNode node = new TreeNode(val);
return node;
}
if(val < root.val) {
root.left = insertIntoBST(root.left,val);
}
if(val > root.val) {
root.right = insertIntoBST(root.right,val);
}
return root;
}
}
450.删除二叉搜索树中的节点
考虑以下几种删除的节点的情况:
-
没找到要删的节点
-
删的是叶子节点(左右都为空)
-
左不为空,右为空,直接让父节点指向它的左孩子
-
左为空,右不为空,直接让父节点指向它的右孩子
-
左不空,右不空(最复杂)
- 我们这里让右子树去继位。左子树安置在 右子树的最左下节点,让它的left指向原先的左子树
- ==递归中套一个小迭代找右子树的最左下节点!==然后就变成左空右不空的情况了!
本题中我们不去遍历整棵二叉树,而是寻找要删的点。删除的逻辑在终止条件里面。
删除逻辑是直接return null或者左右孩子,然后直接在下面用root.left/right接住
- 确定递归函数
TreeNode delete(root,key)
- 终止条件
//没找到删的节点
if(root == null) return null;
if(root.val == key) { //找到了要删的
if(root.left==null && root.right==null) { //删的是叶子节点
return null; //在下面用root.left/right来接住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.left = root.left; //把原先的左子树赋给 最左下节点的左孩子
//接下来移除节点,等同于左空右不空的情况了!
return root.right;
}
}
- 单层递归逻辑
if(key < root.val)
root.left = delete(root.left,key); //返回回来的新节点要用root.left接住
if(key > root.val)
root.right = delete(root.right,key);
return root;
通过直接return root.left或right,然后在上一层root.左右孩子接住返回值
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.right;
else if(root.left != null && root.right == null)
return root.left;
else {
TreeNode cur = root.right;
while(cur.left!=null) {
cur = cur.left;
}
cur.left = root.left;
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;
}
}