Medium草稿★★★★★O(n) 時間 · O(1) 空間
TreeBSTRecursion
Patterns🌳 樹形 DFS
尚未複習過

解法已隱藏 — 先讀題目敘述、自己想想看,再點上方按鈕揭曉。

669Trim a Binary Search TreeTreesMediumTrees

給定一棵 BST 的根節點以及範圍 [low, high],修剪 BST 使得所有節點的值都在 [low, high] 範圍內。修剪後的樹仍須保持 BST 性質。

Example:

Input: root = [1,0,2], low = 1, high = 2 Output: [1,null,2]

Intuition

TIP

利用 BST 性質:節點值太小就往右找,太大就往左找,範圍內就遞迴修剪左右子樹。

Approaches

1. Recursion — O(n) / O(h)
  • Idea: 利用 BST 性質遞迴修剪,超出範圍的子樹直接跳過
  • Time: O(n)
  • Space: O(h),h 為樹高
class Solution {
    fun trimBST(root: TreeNode?, low: Int, high: Int): TreeNode? {
        if (root == null) return null
        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. Iterative — O(n) / O(1)
  • Idea: 先找到根節點在範圍內,再分別處理左右子樹的越界節點
  • Time: O(n)
  • Space: O(1)
class Solution {
    fun trimBST(root: TreeNode?, low: Int, high: Int): TreeNode? {
        // 找到在範圍內的根
        var node = root
        while (node != null && (node.`val` < low || node.`val` > high)) {
            node = if (node.`val` < low) node.right else node.left
        }
        // 修剪左子樹中 < low 的部分
        var curr = node
        while (curr != null) {
            while (curr.left != null && curr.left!!.`val` < low) {
                curr.left = curr.left!!.right
            }
            curr = curr.left
        }
        // 修剪右子樹中 > high 的部分
        curr = node
        while (curr != null) {
            while (curr.right != null && curr.right!!.`val` > high) {
                curr.right = curr.right!!.left
            }
            curr = curr.right
        }
        return node
    }
}

🔑 Takeaways