LeetCode669.修剪二叉搜索树

338 阅读2分钟

「这是我参与11月更文挑战的第14天,活动详情查看:2021最后一次更文挑战

修剪二叉搜索树

题目

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

所以结果应当返回修剪好的二叉搜索树的新的根节点。注意,根节点可能会根据给定的边界发生改变。

示例 1: image.png

输入: root = [1,0,2], low = 1, high = 2
输出: [1,null,2]

示例 2:

image.png

输入: root = [3,0,4,null,2,null,null,1], low = 1, high = 3
输出: [3,2,null,1]

示例 3

输入: root = [1], low = 1, high = 2
输出: [1]

示例 4:

输入:root = [1,null,2], low = 1, high = 3
输出:[1,null,2]

示例 5:

输入:root = [1,null,2], low = 2, high = 4
输出:[2]

提示:

  • 树中节点数在范围 [1, 104] 内
  • 0 <= Node.val <= 104
  • 树中每个节点的值都是唯一的
  • 题目数据保证输入是一棵有效的二叉搜索树
  • 0 <= low <= high <= 104

解法

迭代法

  • 首先判断根节点是否为空,然后寻找第一个符合[low,high]的根节点,这个根节点迭代为root节点 迭代的方法是:如果root.val<low,证明符合区间的节点存在于右子树,如果root.val>low,证明符合区间的节点存在于左子树
  • 为了方便最后返回,不直接使用root迭代修剪树枝,而是使用一个cur节点进行修剪树枝的迭代,如果cur不为空,判断其左子节点的val值是否在[low,high]中,如果不符合,将父节点的连接移动左子节点的右子树上(左子节点及其左子树必定不符合要求,改变链接即将其删除),继续判断新的节点是否符合要求,如果不符合cur指向cur.left,重复以上迭代操作
  • cur重新指向root节点,修剪右子树。如果cur不为空,判断其右子节点的val值是否在[low,high]中,如果不符合,将父节点的连接移动右子节点的左子树上(右子节点及其右子树必定不符合要求,改变链接即将其删除),继续判断新的节点是否符合要求,如果不符合cur指向cur.right,重复以上迭代操作
var trimBST = function(root, low, high) {
    // 如果根节点为null,返回一个null
    if(root === null) {
        return null;
    }
    // 寻找第一个符合[low,high]的根节点,这个根节点迭代为root节点
    while(root !==null &&(root.val<low||root.val>high)) {
        if(root.val<low) {
            root = root.right;
        }else {
            root = root.left;
        }
    }
    // 为了方便最后返回,不直接使用root迭代修剪树枝,而是使用一个cur节点
    let cur = root;
    // 寻找左子树中最接近但比low小的节点,改变指向,修剪不符合的节点
    while(cur!==null) {
        while(cur.left&&cur.left.val<low) {
            cur.left = cur.left.right;
        }
        cur = cur.left;
    }
    cur =  root;
    // 寻找左子树中最接近但比high大的节点,改变指向,修剪不符合的节点
    while(cur!==null) {
        while(cur.right&&cur.right.val>high) {
            cur.right = cur.right.left;
        }
        cur = cur.right;
    }
    return root;
};