day21 代码随想录算法训练营 二叉树专题8

1 今日打卡题

修剪二叉搜索树 669. 修剪二叉搜索树 - 力扣(LeetCode)

将有序数组转换为二叉树 108. 将有序数组转换为二叉搜索树 - 力扣(LeetCode)

把二叉搜索树转换为累加树 538. 把二叉搜索树转换为累加树 - 力扣(LeetCode)

2 修剪二叉搜索树

2.1 思路

如果当前节点值大于 high,说明当前节点及其右子树都不符合条件,只需递归处理左子树并返回;

如果当前节点值小于 low,说明当前节点及其左子树都不符合条件,只需递归处理右子树并返回;

如果当前节点值在 [low, high] 范围内,则保留该节点,递归修剪其左、右子树后拼接到当前节点上,最后返回当前节点;

递归终止条件:遇到空节点时直接返回 null。

核心逻辑:利用 BST 的特性减少无效递归(节点值超限时,直接跳过一侧子树),递归修剪符合条件的节点;

递归终止:遇到空节点返回 null;

节点保留规则:值在 [low, high] 范围内时,保留节点并递归修剪其左右子树;值超限则返回另一侧子树的修剪结果。

2.2 实现代码

java 复制代码
class Solution {
    /**
     * 修剪二叉搜索树,只保留值在 [low, high] 范围内的节点
     * @param root 二叉搜索树的根节点
     * @param low 下限值
     * @param high 上限值
     * @return 修剪后的二叉搜索树根节点
     */
    public TreeNode trimBST(TreeNode root, int low, int high) {
        // 递归终止条件:当前节点为空,直接返回null
        if(root == null) return null;
        
        // 情况1:当前节点值大于high,根据BST特性,其右子树所有节点都大于high,无需处理
        // 只需递归修剪左子树,并返回左子树修剪后的结果
        if(root.val > high) {
            TreeNode left = trimBST(root.left, low, high);
            return left;
        }
        
        // 情况2:当前节点值小于low,根据BST特性,其左子树所有节点都小于low,无需处理
        // 只需递归修剪右子树,并返回右子树修剪后的结果
        if(root.val < low) {
            TreeNode right = trimBST(root.right, low, high);
            return right;
        }
        
        // 情况3:当前节点值在[low, high]范围内,保留该节点
        // 递归修剪左子树,将修剪后的左子树赋值给当前节点的左孩子
        root.left = trimBST(root.left, low, high);
        // 递归修剪右子树,将修剪后的右子树赋值给当前节点的右孩子
        root.right = trimBST(root.right, low, high);
        
        // 返回保留的当前节点(已完成左右子树的修剪)
        return root;
    }
}

模拟:

修剪范围:low=1,high=3(只保留值为 1、2、3 的节点)。

执行步骤:

调用 trimBST(3, 1, 3):

3 在 [1,3] 范围内,先处理左子树(节点 0),再处理右子树(节点 4)。

处理左子树:调用 trimBST(0, 1, 3):

0 < 1,需要递归处理其右子树(节点 2),返回右子树的修剪结果。

调用 trimBST(2, 1, 3):

2 在 [1,3] 范围内,处理左子树(节点 1),右子树为空(返回 null)。

调用 trimBST(1, 1, 3):

1 在 [1,3] 范围内,左右子树都为空,返回节点 1。

回到节点 2 的处理:

节点 2 的左孩子赋值为节点 1,右孩子为 null,返回节点 2。

回到节点 0 的处理:

节点 0 < 1,返回节点 2(其右子树的修剪结果),因此节点 3 的左孩子变为节点 2。

处理节点 3 的右子树:调用 trimBST(4, 1, 3):

4 > 3,递归处理其左子树(为空),返回 null,因此节点 3 的右孩子为 null。

最终返回节点 3,修剪后的树结构:

3 将有序数组转换为二叉树

3.1 思路

递归终止条件:当左指针 > 右指针时,说明当前子树无节点,返回 null;

确定根节点:取数组中间位置 mid 的元素作为当前子树的根节点;

构建左子树:递归处理数组左半部分 [left, mid-1],作为根节点的左子树;

构建右子树:递归处理数组右半部分 [mid+1, right],作为根节点的右子树;

返回当前根节点:完成当前子树的构建并返回。

3.2 实现代码

java 复制代码
class Solution {
    // 主方法:将有序数组转换为平衡二叉搜索树
    public TreeNode sortedArrayToBST(int[] nums) {
        // 调用递归构建方法,初始范围是整个数组(左边界0,右边界nums.length-1)
        TreeNode root = build(nums, 0, nums.length - 1);
        return root;
    }

    // 递归构建方法:参数为数组、当前子树对应的数组左边界、右边界
    public TreeNode build(int[] nums, int left, int right) {
        // 递归终止条件:左边界超过右边界,说明当前子树无节点,返回null
        if (left > right) {
            return null;
        }

        // 1. 找中间位置作为根节点(保证左右子树节点数尽可能相等,平衡)
        int mid = (left + right) / 2;
        // 2. 创建当前子树的根节点(值为中间位置的元素)
        TreeNode root = new TreeNode(nums[mid]);
        // 3. 递归构建左子树:范围是[left, mid-1],挂到当前根节点的左孩子
        root.left = build(nums, left, mid - 1);
        // 4. 递归构建右子树:范围是[mid+1, right],挂到当前根节点的右孩子
        root.right = build(nums, mid + 1, right);

        // 返回当前构建好的子树根节点
        return root;
    }
}

4 把二叉搜索树转换为累加树

4.1 思路

要实现累加,关键是逆中序遍历 (右→根→左):

先遍历右子树(值更大的节点),再处理当前节点,最后遍历左子树;

用一个全局 / 引用变量记录 "累加和",遍历到当前节点时,将累加和赋值给当前节点,再把当前节点原值加到累加和中;

递归终止条件:遇到空节点直接返回。

4.2 实现代码

java 复制代码
class Solution {
    // 全局变量:记录累加和(初始为0)
    private int sum = 0;

    public TreeNode convertBST(TreeNode root) {
        // 递归入口:逆中序遍历整棵树
        traversal(root);
        return root;
    }

    // 逆中序遍历函数(右→根→左)
    private void traversal(TreeNode node) {
        // 递归终止:节点为空,直接返回
        if (node == null) {
            return;
        }

        // 1. 先遍历右子树(值更大的节点)
        traversal(node.right);

        // 2. 处理当前节点:累加和赋值给当前节点,再更新累加和
        sum += node.val; // 累加和 = 原有累加和 + 当前节点原值
        node.val = sum;  // 当前节点新值 = 累加和

        // 3. 再遍历左子树(值更小的节点)
        traversal(node.left);
    }
}
相关推荐
Wect7 小时前
LeetCode 130. 被围绕的区域:两种解法详解(BFS/DFS)
前端·算法·typescript
NAGNIP19 小时前
一文搞懂深度学习中的通用逼近定理!
人工智能·算法·面试
颜酱1 天前
单调栈:从模板到实战
javascript·后端·算法
CoovallyAIHub1 天前
仿生学突破:SILD模型如何让无人机在电力线迷宫中发现“隐形威胁”
深度学习·算法·计算机视觉
CoovallyAIHub1 天前
从春晚机器人到零样本革命:YOLO26-Pose姿态估计实战指南
深度学习·算法·计算机视觉
CoovallyAIHub1 天前
Le-DETR:省80%预训练数据,这个实时检测Transformer刷新SOTA|Georgia Tech & 北交大
深度学习·算法·计算机视觉
CoovallyAIHub1 天前
强化学习凭什么比监督学习更聪明?RL的“聪明”并非来自算法,而是因为它学会了“挑食”
深度学习·算法·计算机视觉
CoovallyAIHub1 天前
YOLO-IOD深度解析:打破实时增量目标检测的三重知识冲突
深度学习·算法·计算机视觉
NAGNIP2 天前
轻松搞懂全连接神经网络结构!
人工智能·算法·面试
NAGNIP2 天前
一文搞懂激活函数!
算法·面试