Medium草稿★★★★★O(n) 時間 · O(n) 空間
GreedyBFSSliding WindowString
Patterns🌊 廣度優先 BFS🪟 滑動視窗🪙 貪心
尚未複習過

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

1871Jump Game VIIGreedyMediumGreedy

給定一個二進位字串 s(以 ‘0’ 開頭)和兩個整數 minJumpmaxJump。從位置 0 出發,每次可以跳 minJumpmaxJump 步,但只能落在 ‘0’ 的位置上。判斷能否到達最後一個位置。

Example:

Input: s = “011010”, minJump = 2, maxJump = 3 Output: true

Intuition

TIP

用滑動視窗或前綴和記錄哪些位置可達,避免重複檢查。

Approaches

1. BFS + Optimization — O(n) / O(n)
  • Idea: 用 BFS 搜索,但維護一個指標避免重複掃描已處理的範圍。
  • Time: O(n)
  • Space: O(n)
class Solution {
    fun canReach(s: String, minJump: Int, maxJump: Int): Boolean {
        val n = s.length
        if (s[n - 1] == '1') return false

        val queue = ArrayDeque<Int>()
        queue.add(0)
        var farthest = 0

        while (queue.isNotEmpty()) {
            val i = queue.removeFirst()
            val start = maxOf(i + minJump, farthest + 1)
            val end = minOf(i + maxJump, n - 1)
            for (j in start..end) {
                if (s[j] == '0') {
                    if (j == n - 1) return true
                    queue.add(j)
                }
            }
            farthest = maxOf(farthest, end)
        }
        return false
    }
}
⭐ 2. Prefix Sum DP — O(n) / O(n)
  • Idea: dp[i] 表示位置 i 是否可達。用前綴和記錄 dp 中的可達位置數,O(1) 查詢某範圍內是否有可達位置。
  • Time: O(n)
  • Space: O(n)
class Solution {
    fun canReach(s: String, minJump: Int, maxJump: Int): Boolean {
        val n = s.length
        if (s[n - 1] == '1') return false

        val dp = BooleanArray(n)
        dp[0] = true
        var reachable = 0 // 滑動視窗內可達位置的數量

        for (i in 1 until n) {
            if (i >= minJump) reachable += if (dp[i - minJump]) 1 else 0
            if (i > maxJump) reachable -= if (dp[i - maxJump - 1]) 1 else 0
            dp[i] = s[i] == '0' && reachable > 0
        }
        return dp[n - 1]
    }
}

🔑 Takeaways