1. 修剪二叉树(leetcode 669)
这题关键在于不在范围内的树他的子树可能也在范围内,所以需要重构二叉树。
这题我们可以尝试用递归法的方式,前序遍历深度优先搜索树
递归三部曲:
1. 参数以及返回值:参数为当前节点,因为我们需要做修剪,因此通过返回值来移除节点
2. 确认终止条件:遇到空间点直接返回
3. 确定当前层逻辑:如果当前root小于low,往右递归,返回右子树返回条件的头节点
if root.val < low:
right = self.trimBST(root.right, low, hight)
return right
在这个步骤中我们就相当于已经把当前节点删除了,把保留下来的符合条件的右节点嫁接了过来。
总体的代码如下:
class Solution:
def trimBST(self, root: Optional[TreeNode], low: int, high: int) -> Optional[TreeNode]:
if not root:
return None
if root.val < low: #当前层判断是否符合条件
right = self.trimBST(root.right, low, high)
return right
if root.val > high:
left = self.trimBST(root.left, low, high)
return left
#进行嫁接
root.left = self.trimBST(root.left, low, high)
root.right = self.trimBST(root.right, low, high)
return root #这边在最后返回头节点。
这题的难点在于我们是怎么修剪掉我们不需要的节点,以及嫁接我们所需要的节点的。
2. 有序数组转化为BST(leetcode 108)
这题首先注意到他想让我们构建的是height-balanced BST,因此我们就不能用单边构建的方法。
如果不能单边构建,我们就不能使用迭代法,因此这题最好的方法是通过递归法,以中点为当前层节点,分别像左右递归,作为当前层的左右子集。
三部曲:
1. 参数:因为我们需要找中点,所以我们需要界定好当前层的左右范围,因此参数为数组,左范围,和右范围。
2. 终止条件:左边肯定要比右边小的,换言之当右边比左边小则终止
3. 当前层逻辑:找到中点,让中点为当前层节点,同时左右子树分别更新区间进行递归
class Solution:
def sort(self, nums, left, right):
if left <= right:
mid = (left + right) // 2
root = TreeNode(nums[mid])
root.left = self.sort(nums, left, mid - 1)
root.right = self.sort(nums, mid + 1, right)
return root
def sortedArrayToBST(self, nums: List[int]) -> Optional[TreeNode]:
return self.sort(nums, 0, len(nums) - 1)
或者我们也可以用更新nums的方式,这样我们就可以不用left and right作为参数了。
class Solution:
def sortedArrayToBST(self, nums: List[int]) -> Optional[TreeNode]:
if not nums:
return None
mid = (len(nums) -1) // 2
root = TreeNode(nums[mid])
root.left = self.sortedArrayToBST(nums[:mid])
root.right = self.sortedArrayToBST(nums[mid+1:])
return root
注意这种情况是左闭右开,所以root.left这边要取到0到mid的区间,而不是0到mid-1。
3. BST转化成累加树(leetcode 538)
这题注意到累加我们是从右下角的位置开始累加的,他的处理顺序是右中左。我们可以直接用反中序遍历的方法,同时设置指针pre cur来指向前一个节点以及当前节点,在遍历的过程中直接修改我们的树。
递归法在这里的写法是比较简单的,和我们之前的dfs递归差不多写法
class Solution:
def traversal(self, cur):
if not cur:
return None
self.traversal(cur.right)
cur.val = cur.val + self.pre
self.pre = cur.val
self.traversal(cur.left)
return cur
def convertBST(self, root: Optional[TreeNode]) -> Optional[TreeNode]:
self.pre = 0
self.traversal(root)
return root
我们也尝试一下用迭代法,stack来写。
class Solution:
def convertBST(self, root: Optional[TreeNode]) -> Optional[TreeNode]:
if not root: return root
stack = []
cur = root
pre = 0
while cur or stack:
if cur:
stack.append(cur)
cur = cur.right
else:
cur = stack.pop()
cur.val += pre
pre = cur.val
cur = cur.left
return root
这种写法也是和我们之前一直在写的遍历BST的方法一样,唯一不同的只是讲左中右改成了右中左,同时多了一个pre时刻记录叠加值。迭代法很多情况下是比递归法要高效的,我们也要多写。