代码随想录 day 20 二叉树

第六章 二叉树part07

235. 二叉搜索树的最近公共祖先

相对于 二叉树的最近公共祖先 本题就简单一些了,因为 可以利用二叉搜索树的特性。
题目链接/文章讲解:https://programmercarl.com/0235.%E4%BA%8C%E5%8F%89%E6%90%9C%E7%B4%A2%E6%A0%91%E7%9A%84%E6%9C%80%E8%BF%91%E5%85%AC%E5%85%B1%E7%A5%96%E5%85%88.html
视频讲解:https://www.bilibili.com/video/BV1Zt4y1F7ww

701.二叉搜索树中的插入操作

本题比想象中的简单,大家可以先自己想一想应该怎么做,然后看视频讲解,就发现 本题为什么比较简单了。
题目链接/文章讲解:https://programmercarl.com/0701.%E4%BA%8C%E5%8F%89%E6%90%9C%E7%B4%A2%E6%A0%91%E4%B8%AD%E7%9A%84%E6%8F%92%E5%85%A5%E6%93%8D%E4%BD%9C.html
视频讲解:https://www.bilibili.com/video/BV1Et4y1c78Y

450.删除二叉搜索树中的节点

相对于 插入操作,本题就有难度了,涉及到改树的结构
题目链接/文章讲解:https://programmercarl.com/0450.%E5%88%A0%E9%99%A4%E4%BA%8C%E5%8F%89%E6%90%9C%E7%B4%A2%E6%A0%91%E4%B8%AD%E7%9A%84%E8%8A%82%E7%82%B9.html
视频讲解:https://www.bilibili.com/video/BV1tP41177us

235. 二叉搜索树的最近公共祖先

题目链接

https://leetcode.cn/problems/lowest-common-ancestor-of-a-binary-search-tree/description/

解题思路

1.因为是有序树,所以 如果 中间节点是 q 和 p 的公共祖先,那么 中节点的数组 一定是在 [p, q]区间的
2.只要从上到下去遍历,遇到 cur节点是数值在[p, q]区间中则一定可以说明该节点cur就是p 和 q的公共祖先。 那问题来了,一定是最近公共祖先吗?
证明一下:
因为是二叉搜索树,中间节点在[p, q]区间,如果遇到了第一个节点在这个区间:
2.1 向左都是小于这个节点的,所以左子树不可能存在q
2.2 向右都是大于这个节点的,所在右子树不可能存在p
所以遇到的第一个节点一定是p和q的最近公共祖先。
3.递归遍历顺序,本题就不涉及到 前中后序了(这里没有中节点的处理逻辑,遍历顺序无所谓了)

code

    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;
            }
        }
        //此时就说明在p和q之间了
        return root;
    }

701.二叉搜索树中的插入操作

题目链接

https://leetcode.cn/problems/insert-into-a-binary-search-tree/description/

解题思路

有多种有效的插入方式,还可以重构二叉搜索树,一下子吓退了不少人,可以不用考虑改变树结构的插入方式,那么就简单了,就说明解题的时候审题的重要性,有些可忽略有些不可忽略。
利用返回值完成新加入的节点与其父节点的赋值操作的思想:
通过递归函数返回值完成了新加入节点的父子关系赋值操作,下一层将节点返回,本层用root.left或root.right 接住
解题流程:
只要按照二叉搜索树的规则去遍历,遇到空节点就插入节点就可以了
根据二叉搜索树的特性,去判断它是向左递归还是向右
val<root.val 去左子树
val>root.val 去右子树
直到找到一个null值,说明找到了它的位置,这个null值的空节点就是这个val新节点,返回给递归函数赋值给腹父节点。

code

    public TreeNode insertIntoBST(TreeNode root, int val) {
        if(root==null){
            return new TreeNode(val);
        }
        if(val < root.val){
            root.left=insertIntoBST(root.left,val);
        }
        if(val > root.val){
            root.right=insertIntoBST(root.right,val);
        }
        return root;
    }

450. 删除二叉搜索树中的节点

题目链接

https://leetcode.cn/problems/delete-node-in-a-bst/description/

解题思路

删除节点的操作是通过返回值来操作,通过递归返回值来把新节点赋值给父节点。
root==null 是终止条件 找到要删的点也是终止条件,找到删的点后要处理逻辑,最终返回新的节点给父节点。
分析下面几种情况,可以画图模拟下
分治递归,像是前序遍历
分治递归的核心思想是将一个问题分解为多个子问题分别求解,然后将子问题的解组合起来得到原问题的解
在前中后序这些遍历方法中,都遵循分治递归的思想:
分解问题:对每个节点,都将其左子树和右子树视为子问题。
解决子问题:通过递归调用,在子树上继续执行相同的遍历操作。
合并结果:根据遍历的顺序,将子树的遍历结果组合起来。
前序、中序和后序遍历都可以视为分治递归的具体应用。

code

    public TreeNode deleteNode(TreeNode root, int key) {
        //1.没找到要删除的节点 返回null
        if(root==null){
            return null;
        }
        //找到要删除的节点
        if(root.val==key){
            //2.左右都未null 不需要额外处理直接返回null就是删除当前的节点
           if(root.left==null&&root.right==null){
              return null;
            //3.左右都不为null 把左节点放入到右节点的最左节点,分析搜索树的特性即可
           }else if(root.left!=null&&root.right!=null){
                TreeNode cur=root.right;
                while(cur.left!=null){
                    cur=cur.left;
                }
                cur.left=root.left;
              return root.right;
           //4.左不为null右为null 返回节点即可    
           }else if(root.left!=null){
                return root.left;
           //5.右不为null 左为null 返回节点即可    
           }else if(root.right!=null){
                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;
    }

扩展 根据数组构建二叉树

public class BinaryTreeBuilder {


    // 根据数组构建二叉树
    public static TreeNode buildTree(Integer[] nodes) {
        if (nodes == null || nodes.length == 0) {
            return null;
        }

        Queue<TreeNode> queue = new LinkedList<>();
        TreeNode root = new TreeNode(nodes[0]);
        queue.add(root);

        int i = 1;
        while (!queue.isEmpty() && i < nodes.length) {
            TreeNode current = queue.poll();

            if (i < nodes.length && nodes[i] != null) {
                current.left = new TreeNode(nodes[i]);
                queue.add(current.left);
            }
            i++;

            if (i < nodes.length && nodes[i] != null) {
                current.right = new TreeNode(nodes[i]);
                queue.add(current.right);
            }
            i++;
        }

        return root;
    }
}
    public static void main(String[] args) {
        TreeNode treeNode = BinaryTreeBuilder.buildTree(new Integer[]{3,2,5,null,null,4,10,null,null,8,15,7});
        new Solution().deleteNode(treeNode, 5);
    }

相关推荐

  1. 代码随想 day 20

    2024-07-23 00:14:03       17 阅读
  2. 代码随想刷——day22

    2024-07-23 00:14:03       50 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-07-23 00:14:03       52 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-07-23 00:14:03       54 阅读
  3. 在Django里面运行非项目文件

    2024-07-23 00:14:03       45 阅读
  4. Python语言-面向对象

    2024-07-23 00:14:03       55 阅读

热门阅读

  1. 学懂C语言系列(二):C程序结构

    2024-07-23 00:14:03       19 阅读
  2. StringBuilder类

    2024-07-23 00:14:03       12 阅读
  3. thinkphp6连接kingbase数据库

    2024-07-23 00:14:03       11 阅读
  4. 压缩Mojo模型:轻装上阵的机器学习模型

    2024-07-23 00:14:03       15 阅读
  5. C++11 智能指针之shared_from_this

    2024-07-23 00:14:03       16 阅读
  6. frp、FTP服务

    2024-07-23 00:14:03       12 阅读
  7. Apache虚拟主机VirtualHost配置项详解

    2024-07-23 00:14:03       15 阅读