【2022-09-10每日一题】669. 修剪二叉搜索树
2022-09-10
2分钟阅读时长
2022-09-10每日一题:669. 修剪二叉搜索树
- 难度:Medium
- 标签:树 、 深度优先搜索 、 二叉搜索树 、 二叉树
给你二叉搜索树的根节点 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
/**
* Definition for a binary tree node.
* type TreeNode struct {
* Val int
* Left *TreeNode
* Right *TreeNode
* }
*/
func trimBST(root *TreeNode, low int, high int) *TreeNode {
if root == nil {
return nil
}
// 根据二叉搜索树定义,当前节点小于最小值,只看右子树
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
}
复杂度分析
- 时间复杂度:O(n),其中 n 为二叉树的结点数目。
- 空间复杂度:O(n)。递归栈最坏情况下需要 O(n) 的空间。
方法二:迭代
思路
如果一个结点 node 符合要求,即它的值位于区间 [low,high],那么它的左子树与右子树应该如何修剪?
左子树的修剪:
node 的左结点为空结点:不需要修剪
node 的左结点非空:
如果它的左结点 left 的值小于 low,那么 left 以及 left 的左子树都不符合要求,我们将 node 的左结点设为 left 的右结点,然后再重新对 node 的左子树进行修剪。
如果它的左结点 left 的值大于等于 low,又因为 node 的值已经符合要求,所以 left 的右子树一定符合要求。基于此,我们只需要对 left 的左子树进行修剪。我们令 node 等于 left ,然后再重新对 node 的左子树进行修剪。
以上过程可以迭代处理。对于右子树的修剪同理。
我们对根结点进行判断,如果根结点不符合要求,我们将根结点设为对应的左结点或右结点,直到根结点符合要求,然后将根结点作为符合要求的结点,依次修剪它的左子树与右子树。
代码
/**
* Definition for a binary tree node.
* type TreeNode struct {
* Val int
* Left *TreeNode
* Right *TreeNode
* }
*/
func trimBST(root *TreeNode, low int, high int) *TreeNode {
for root != nil && (root.Val < low || root.Val > high) {
if root.Val > high {
root = root.Left
} else {
root = root.Right
}
}
if root == nil {
return nil
}
// 修剪左子树
for node := root; node.Left != nil; {
if node.Left.Val < low { // 丢弃左子树
node.Left = node.Left.Right
} else {
node = node.Left
}
}
// 修剪右子树
for node := root; node.Right != nil; {
if node.Right.Val > high { // 丢弃右子树
node.Right = node.Right.Left
} else {
node = node.Right
}
}
return root
}
复杂度分析
- 时间复杂度:O(n),其中 n 为二叉树的结点数目。
- 空间复杂度:O(1)。