「这是我参与11月更文挑战的第14天,活动详情查看:2021最后一次更文挑战」
修剪二叉搜索树
题目
给你二叉搜索树的根节点 root ,同时给定最小边界low 和最大边界 high。通过修剪二叉搜索树,使得所有节点的值在[low, high]中。修剪树不应该改变保留在树中的元素的相对结构(即,如果没有被移除,原有的父代子代关系都应当保留)。可以证明,存在唯一的答案。
所以结果应当返回修剪好的二叉搜索树的新的根节点。注意,根节点可能会根据给定的边界发生改变。
示例 1:
输入: root = [1,0,2], low = 1, high = 2
输出: [1,null,2]
示例 2:
输入: 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;
};