代码随想录算法训练营day23 | 669. 修剪二叉搜索树 108.将有序数组转换为二叉搜索树 538.把二叉搜索树转换为累加树

66 阅读4分钟

669. 修剪二叉搜索树

给你二叉搜索树的根节点 root ,同时给定最小边界low 和最大边界 high。通过修剪二叉搜索树,使得所有节点的值在[low, high]中。修剪树 不应该 改变保留在树中的元素的相对结构 (即,如果没有被移除,原有的父代子代关系都应当保留)。 可以证明,存在 唯一的答案 。
所以结果应当返回修剪好的二叉搜索树的新的根节点。注意,根节点可能会根据给定的边界发生改变。

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

思路

对于二叉搜索树的每个节点,

  • 如果该节点的值在[low, high]范围内,那么,
    • 当前节点的左子树的节点都小于high,所以要找到左子树中大于 low的节点。
    • 当前节点的右子树的节点都大于low,所以要找到右子树中小于 high的节点。
  • 如果该节点的值大于 low,那么当前节点和它左子树的所有节点的值都小于low,不符合条件;满足条件的值只会出现它的右子树,返回递归遍历右子树后的结果。
  • 否则,该节点的值小于hign,当前节点和它右子树的所有节点的值都大于high,不符合条件;满足条件的值只会出现它的左子树,返回递归遍历左子树后的结果。

代码

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    public TreeNode trimBST(TreeNode root, int low, int high) {

        if(root == null){
            return null;
        }

        // 对于一个满足条件的节点 root , 
        // 左子树 = 大于 low 的节点
        // 右子树 = 小于 high 的节点

        if(root.val >= low && root.val <= high){
            root.left = trimBST(root.left,low,high);
            root.right = trimBST(root.right,low,high);
            return root;
        }

        // 如果 当前节点小于low, 那么满足条件的值只可能出现在右子树
        if(root.val < low){
            return trimBST(root.right,low,high);
        }

        // 当前节点大于 high , 满足条件的值只可能出现在左子树
        return trimBST(root.left,low,high);

    }
}

108.将有序数组转换为二叉搜索树

给你一个整数数组 nums ,其中元素已经按 升序 排列,请你将其转换为一棵 高度平衡 二叉搜索树。
高度平衡 二叉树是一棵满足「每个节点的左右两个子树的高度差的绝对值不超过 1 」的二叉树。

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

思路

在有序数组中,每次取最中间的元素作为当前节点的值,并以此元素将当前区间分成左右两部分,作为当前节点的左右子树,这样,左右子树的节点数相等(或相差1,如果当前数组元素为偶数),满足平衡的要求;再分别对左子树和右子树递归进行,最终得到一棵平衡的二叉搜索树。

代码

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    public TreeNode sortedArrayToBST(int[] nums) {
        return traversal(nums, 0, nums.length - 1);
    }

    // 使用左闭右闭区间
    // [left, right]
    private TreeNode traversal(int nums[], int left, int right){

        if(left > right){
            return null;
        }

        // 中间下标
        // 自动向下取整
        int middle = (left + right) / 2;

        TreeNode node = new TreeNode(nums[middle]);

        node.left = traversal(nums, left, middle - 1);
        node.right = traversal(nums, middle + 1, right);

        return node;
    }
}

538.把二叉搜索树转换为累加树

给出二叉 搜索 树的根节点,该树的节点值各不相同,请你将其转换为累加树(Greater Sum Tree),使每个节点 node 的新值等于原树中大于或等于 node.val 的值之和。

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

思路

累加树让每个节点 node 的新值等于原树中大于或等于 node.val 的值之和,那么二叉树中值最大的节点的新值就是它本身,任意比该值小的节点都要加上这个值。
在二叉搜索树的任一棵子树中,当前节点为node,根据二叉搜索树的定义,node.right.val > node.val > node.left.val 成立。因此遍历的顺序是右子树、中间节点、左子树,即右中左的遍历方式。
遍历完一个节点后,将该节点的新值返回,并作为参数传到下一个要遍历的节点。

代码

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    public TreeNode convertBST(TreeNode root) {
        traversal(root, 0);
        return root;
    }

    // 右中左的遍历方式
    private int traversal(TreeNode node, int sum){

        if(node == null){
            return sum;
        }

        // 右
        int sumRight = traversal(node.right,sum);

        // 中
        node.val = node.val + sumRight;

        int sumLeft = traversal(node.left, node.val);

        return sumLeft;

    }
}