代码随想录算法训练营 Day 18

2 minute read

Published:

Q1. LeetCode 669

考虑多种情况:

  1. 当前节点在范围之内 -> 继续遍历左右子树
  2. 当前节点小于最小值 -> 遍历右子树并返回新的右子树
  3. 当前节点大于最大值 -> 遍历左子树并返回新的左子树

解法1. 递归法

class Solution:
    def trimBST(self, root: Optional[TreeNode], low: int, high: int) -> Optional[TreeNode]:
        if not root:
            return None
        
        if root.val < low:
            r = self.trimBST(root.right, low, high)
            return r
        
        if root.val > high:
            l = self.trimBST(root.left, low, high)
            return l
        
        root.left = self.trimBST(root.left, low, high)
        root.right = self.trimBST(root.right, low, high)

        return root

解法2: 迭代法

class Solution:
    def trimBST(self, root: Optional[TreeNode], low: int, high: int) -> Optional[TreeNode]:
        if not root:
            return None
        
        # 处理头节点
        while root and (root.val < low or root.val > high):
            if root.val < low:
                root = root.right
            else:
                root = root.left
        
        curr = root
        # 头节点已经在范围之内,接下来需要修剪其左子树和右子树
        while curr:
            while curr.left and curr.left.val < low:
                # 左节点值不在范围之内,用左节点的右孩子替换
                curr.left = curr.left.right
            curr = curr.left

        curr = root
        while curr:
            while curr.right and curr.right.val > high:
                # 右节点不在范围之内,用右节点的左孩子替换
                curr.right = curr.right.left
            curr = curr.right
        
        return root

Q2. LeetCode 108

平衡二叉搜索树,因此取数组的中间元素作为根节点,左为左子树,右为右子树

解法1: 递归法

class Solution:
    def sortedArrayToBST(self, nums: List[int]) -> Optional[TreeNode]:
        if not nums:
            return
        
        mid = len(nums) // 2
        root = TreeNode(nums[mid])
        root.left = self.sortedArrayToBST(nums[:mid])
        root.right = self.sortedArrayToBST(nums[mid + 1:])

        return root

解法2: 迭代法

from collections import deque

class Solution:
    def sortedArrayToBST(self, nums: List[int]) -> TreeNode:
        if len(nums) == 0:
            return None
        
        root = TreeNode(0)  # 初始根节点
        nodeQue = deque()   # 放遍历的节点
        leftQue = deque()   # 保存左区间下标
        rightQue = deque()  # 保存右区间下标
        
        nodeQue.append(root)               # 根节点入队列
        leftQue.append(0)                  # 0为左区间下标初始位置
        rightQue.append(len(nums) - 1)     # len(nums) - 1为右区间下标初始位置

        while nodeQue:
            curNode = nodeQue.popleft()
            left = leftQue.popleft()
            right = rightQue.popleft()
            mid = left + (right - left) // 2

            curNode.val = nums[mid]  # 将mid对应的元素给中间节点

            if left <= mid - 1:  # 处理左区间
                curNode.left = TreeNode(0)
                nodeQue.append(curNode.left)
                leftQue.append(left)
                rightQue.append(mid - 1)

            if right >= mid + 1:  # 处理右区间
                curNode.right = TreeNode(0)
                nodeQue.append(curNode.right)
                leftQue.append(mid + 1)
                rightQue.append(right)

        return root

Q3. LeetCode 538

累加顺序:右中左,因此按照这个顺序进行遍历,先找到最右节点,然后依次按照反中序遍历进行累加

解法1: 递归法

class Solution:
    def convertBST(self, root: Optional[TreeNode]) -> Optional[TreeNode]:
        prev = 0
        def dfs(node):
            if not node:
                return
            dfs(node.right)
            nonlocal prev
            node.val += prev
            prev = node.val
            dfs(node.left)
        
        dfs(root)

        return root

解法2: 迭代法 (依然可以采用统一写法,只是需要变换顺序)

class Solution:
    def convertBST(self, root: Optional[TreeNode]) -> Optional[TreeNode]:
        if not root:
            return
        stack = [root]
        prev = 0
        while stack:
            curr = stack.pop()
            if curr:
                if curr.left:
                    stack.append(curr.left) #左
                stack.append(curr)          #中
                stack.append(None)
                
                if curr.right:
                    stack.append(curr.right)#右
            else:
                curr = stack.pop()
                curr.val += prev
                prev = curr.val

        return root