难度中等770收藏分享切换为英文接收动态反馈
给你二叉搜索树的根节点 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]提示:
- 树中节点数在范围
[1, 104]内 0 <= Node.val <= 104- 树中每个节点的值都是 唯一 的
- 题目数据保证输入是一棵有效的二叉搜索树
0 <= low <= high <= 104
你修剪的方式不对,我来给你纠正一下!| LeetCode:669. 修剪二叉搜索树
1、递归法
这道题比起删除二叉搜索树的节点要难的就是我们不只是要删一个节点,并且还得保持原来这个二叉搜索树的结构,所以我们不能调用删除函数直接删除。
既然我们可能遇到出边界的节点,但是其左右子树可能是符合边界的,我们就得继续递归到这些子树进行判断,比如下图,我们要的是 [1, 3] 区间,那么我们就得把图中的 0 和 4 给去掉,但是如果直接将 0 这个节点删掉,那么它的右子树原来是符合边界的,也统统被删了,这样子就错了!
正确的做法是如果遇到小于边界 low 的话,我们只需要判断其右子树是否有效,所以我们递归到其右子树;而如果遇到大于边界 high 的话,我们只需要判断其左子树是否有效,那么递归到其左子树。
如果它们的左右子树都还是无效,最后就会走到 nullptr,然后返回 nullptr,就相对于是都无效,符合我们的预期!
如果其中有些节点是有效的,那么我们要处理一下这些符合的节点,就是将当前节点的左右子树继续链接到原来 trimBST() 去递归其左右子树的有效节点,最后会返回一个当前节点 root 回来。上述解释比较抽象,需要结合图像思考!
class Solution {
public:
TreeNode* trimBST(TreeNode* root, int low, int high) {
if(root == nullptr)
return nullptr;
// 若不在范围内则得继续递归到其反方向的子树判断是否有效
if(root->val < low)
return trimBST(root->right, low, high);
if(root->val > high)
return trimBST(root->left, low, high);
// 若在范围内则将左右子树链接上递归后得到的左右子树
root->left = trimBST(root->left, low, high);
root->right = trimBST(root->right, low, high);
return root;
}
};2、迭代法
因为二叉搜索树的有序性,不需要使用栈模拟递归的过程。
在剪枝的时候,可以分为三步:
- 将 root 移动到 [L, R] 范围内,注意是左闭右闭区间
- 剪枝左子树
- 剪枝右子树
class Solution {
public:
TreeNode* trimBST(TreeNode* root, int low, int high) {
if(root == nullptr)
return nullptr;
// 先将root移动到【low,high】区间
while(root != nullptr && (root->val < low || root->val > high))
{
if(root->val < low)
root = root->right;
else
root = root->left;
}
// 当前root已经在【low,high】区间,现在将不符合的左子树进行剪枝
TreeNode* cur = root;
while(cur != nullptr)
{
while(cur->left != nullptr && cur->left->val < low)
{
cur->left = cur->left->right;
}
cur = cur->left;
}
// 现在将不符合的右子树进行剪枝
cur = root;
while(cur != nullptr)
{
while(cur->right != nullptr && cur->right->val > high)
{
cur->right = cur->right->left;
}
cur = cur->right;
}
return root;
}
};