669. 修剪二叉搜索树
题目:给你二叉搜索树的根节点 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
解题思路
1 root.val<low时候,递归修剪右子树
2 root.val>high时候,递归修剪左子树
3 root.val在low和high之间时,root保留,递归处理左右节点然后重新赋值
- 时间复杂度:O(n)
- 空间复杂度:O(1)
class Solution:
def trimBST(self, root: Optional[TreeNode], low: int, high: int) -> Optional[TreeNode]:
if not root:
return None
if root.val < low:
return self.trimBST(root.right, low, high)
if root.val > high:
return self.trimBST(root.left, low, high)
root.left = self.trimBST(root.left, low, high)
root.right = self.trimBST(root.right, low, high)
return root
108. 将有序数组转换为二叉搜索树
题目:给你一个整数数组 nums ,其中元素已经按 升序 排列,请你将其转换为一棵
平衡
二叉搜索树。
示例 1:
输入: nums = [-10,-3,0,5,9]
输出: [0,-3,9,-10,null,5]
解释: [0,-10,5,null,-3,null,9] 也将被视为正确答案:
示例 2:
输入: nums = [1,3]
输出: [3,1]
解释: [1,null,3] 和 [3,1] 都是高度平衡二叉搜索树。
提示:
1 <= nums.length <= 104-104 <= nums[i] <= 104nums按 严格递增 顺序排列
解题思路
构造二叉搜索树最简单的情况就是将有序数组向右子树构建成一条链,这样太简单了,所以需要构建平衡的二叉搜索树。可以取中间节点作为树的中间节点,然后递归的在左区间构建左子树,右区间构建右子树:
1 函数定义nums,left,right,闭区间内构建树
2 终止条件:left>right
3 单层逻辑:取中间值mid构建root,然后left到mid-1构建左子树,mid+1到right构建右子树
- 时间复杂度:O(n),每个数字只访问一次。
- 空间复杂度:O(logn),空间复杂度取决于递归栈的深度,因为是平衡二叉搜索树,没有最坏情况的拉链n的高度,递归栈的深度是 O(logn)。
class Solution:
def sortedArrayToBST(self, nums: List[int]) -> Optional[TreeNode]:
return self.buildBST(nums, 0, len(nums)-1)
def buildBST(self,nums,left,right):
# 递归构建二叉搜索树,[left,right]闭区间
if left > right:
return None
mid = left + (right - left) // 2 # 偶数时取左边的为root
root = TreeNode(val= nums[mid])
root.left = self.buildBST(nums, left, mid-1)
root.right = self.buildBST(nums, mid+1, right)
return root
总结
538. 把二叉搜索树转换为累加树
题目:给出二叉 搜索 树的根节点,该树的节点值各不相同,请你将其转换为累加树(Greater Sum Tree),使每个节点 node 的新值等于原树中大于或等于 node.val 的值之和。
提醒一下,二叉搜索树满足下列约束条件:
- 节点的左子树仅包含键 小于 节点键的节点。
- 节点的右子树仅包含键 大于 节点键的节点。
- 左右子树也必须是二叉搜索树。
注意: 本题和 1038: leetcode-cn.com/problems/bi… 相同
示例 1:
输入: [4,1,6,0,2,5,7,null,null,null,3,null,null,null,8]
输出: [30,36,21,36,35,26,15,null,null,null,33,null,null,null,8]
示例 2:
输入: root = [0,null,1]
输出: [1,null,1]
示例 3:
输入: root = [1,0,2]
输出: [3,3,2]
示例 4:
输入: root = [3,2,4,1]
输出: [7,9,4,10]
提示:
- 树中的节点数介于
0和104之间。 - 每个节点的值介于
-104和104之间。 - 树中的所有值 互不相同 。
- 给定的树为二叉搜索树。
解题思路
右中左顺序遍历,累加中间值。
- 时间复杂度:O(n)
- 空间复杂度:O(n),递归过程中栈的开销,平均情况下为 O(logn),最坏情况下树呈现链状,为 O(n)。
class Solution:
def convertBST(self, root: Optional[TreeNode]) -> Optional[TreeNode]:
self.sum_val = 0
self.traverse(root)
return root
def traverse(self, root: Optional[TreeNode]) -> None:
if not root:
return None
# 先遍历右子树,再累加,最后遍历右子树
self.traverse(root.right)
self.sum_val += root.val
root.val = self.sum_val
self.traverse(root.left)
总结
注意累加树(Greater Sum Tree)是中序遍历时单调递减的树,需要按照右中左的顺序遍历然后累加值。