235. 二叉搜索树的最近公共祖先
- 题目链接:代码随想录
本题特点: ①根据二叉搜索树自动排序的性质,当前只需判断p和q和当前节点的比较②从上向下去递归遍历,第一次遇到 cur节点是数值在[p, q]区间中,那么cur就是 p和q的最近公共祖先。因为二叉排序树决定了只有公共节点能满足既大于又小于③本题与普通二叉树从下向上的后序遍历不同
-
解题思路:
①如果p,q都大于根节点,那么说明最近公共祖先在根节点右边,递归右子树
②如果p,q都小于根节点,那么说明最近公共祖先在根节点左边,递归左子树
③从上去向下递归遍历所以如果p和q,一个大,一个小,那么当前节点就是最近公共祖先
④如果根节点为null,直接返回null,交给上一层,上一层有逻辑会接住
时间和空间都是O(n) 最坏情况下空间复杂度会退化成链
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.right, p, q);
}else if(p.val < root.val && q.val < root.val){
return lowestCommonAncestor(root.left, p, q);
}else{
//p和q一个大,一个小
return root;
}
}
701.二叉搜索树中的插入操作
题目链接:代码随想录
特点:
①利用二叉搜索树的已经排序的性质解题
② 插入问题可以特殊为只有两层的树
-
解题思路:
*
处处理参数和返回值;要有有返回值,便于上一层接住,完成二叉树子节点的赋值-
终止条件:如果遍历到节点为空,就说明好了,这找到位置让你插入,直接插入
-
处理逻辑:如果当前节点值大于目标节点的值,向右递
如果当前节点值小于目标节点的值,向左递
返回条件:因为最后要的是插入之后的二叉搜索树的根节点,所以直接返回每层根节点即可
-
-
时间复杂度:
二叉搜索树平均树高为O(n*log n),最差情况下退化为一个链表,为O(n),因此对应的时间复杂度也可以看出来
所以二叉搜索树的树高非常影响性能,因此查询表常用B树之类的平衡二叉树达到
//递归法
public TreeNode insertIntoBST(TreeNode root, int val) {
//终止条件
if(root == null){
return new TreeNode(val);
}
//处理逻辑
if(root.val < val){
//归上来接住处理,让右子树的节点指向新创立的节点
root.right = insertIntoBST(root.right, val);
}else{
root.left = insertIntoBST(root.left, val);
}
//每一层的根
return root;
}
//迭代法
public TreeNode insertIntoBST(TreeNode root, int val) {
TreeNode node = new TreeNode(val);
if (root == null) {
return node;
}
TreeNode cur = root;
//无限循环,一层层向下找
while (true) {
if (cur.val > val) {
if (cur.left == null) {
cur.left = node;
break;
}
cur = cur.left;
} else {
if (cur.right == null) {
cur.right = node;
break;
}
cur = cur.right;
}
}
return root;
}
450.删除二叉搜索树中的节点⭐️
题目链接:代码随想录
特点:删除节点操作涉及到结构的调整,比插入节点更复杂
而删除中最需要注意的是删除节点的左右孩子都存在,需要调整树的结构
解题步骤: ①找到要删除的节点②执行删除的逻辑
-
解题思路:(这种方法增加了树高)
1> 返回值和参数:设置返回值是为了便于修改树
2> 终止条件:遍历到树为空节点的时候,返回本层的根节点值null
3>处理逻辑:- ①如果当前节点的值大于要找寻的值,那么递归删除左子树
①如果当前节点的值小于要找寻的值,那么递归删除右子树
③如果当前节点的值等于要删除的值
分情况删除:- 1.如果当前节点没有左右子树,那么当前层只需要返回一边的节点即可
2.如果当前处理节点既有左子树,又有右子树,那么处理方式为
找到有边节点的最左叶子结点(右子树最小的一个节点),让该节点指向原本节点的左节点
然后当前节点更新为当前节点的右节点,返回右节点
- 1.如果当前节点没有左右子树,那么当前层只需要返回一边的节点即可
- ①如果当前节点的值大于要找寻的值,那么递归删除左子树
-
两张图便于理解(图片来源)
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
//终止条件
if(root == null){return null;}
//遇到满足条件的节点,立即向上返回
if(root == p || root == q){
return root;
}
//后序遍历
TreeNode left = lowestCommonAncestor(root.left, p, q);
TreeNode right = lowestCommonAncestor(root.right, p, q);
//中间处理逻辑
if(left == null && right == null){
return null;
}
if(left == null && right != null){
return right;
}
if(left != null && right == null){
return left;
}
//返回当前节点
if(left != null && right != null){
return root;
}
return root;
}