0Pricing
Coding Interview Prep · Lektion

Jump Game I und II

Bestimmen Sie Erreichbarkeit und minimale Sprunganzahl mithilfe eines Greedy-Ansatzes zur Bereichserweiterung, der keine dynamische Programmierung benötigt.

Jump Game I und II ist eine kostenlose Coding Interview Prep-Lektion auf CoddyKit. Dies ist Lektion 3 von 4. Du kannst die komplette Lektion unten kostenlos lesen – dann übst du sie direkt im Browser mit einem integrierten Code-Editor und einem KI-Tutor rund um die Uhr. Sie ist Teil des Coding Interview Prep-Lernpfads, und dein Fortschritt wird über Web und CoddyKit-App synchronisiert. Der Coding Interview Prep-Kurs umfasst insgesamt 4 Lektionen.

Jump Game I: Können Sie das Ende erreichen?

Jump Game I (LeetCode 55): Gegeben ist ein Array, in dem nums[i] die maximale Sprungweite vom Index i angibt. Bestimmen Sie, ob Sie ausgehend von Index 0 den letzten Index erreichen können. Für [2, 3, 1, 1, 4] können Sie das Ende erreichen (Sprung von 2 nach 3, und von 3 aus gelangen Sie zum Ende). Für [3, 2, 1, 0, 4] ist dies nicht möglich (Sie landen zwangsläufig auf 0, von wo aus die Sprungweite 0 beträgt). Eine Greedy-Lösung läuft in O(n).

# Can you reach the last index?
nums1 = [2, 3, 1, 1, 4]  # True: 0→1→4 or 0→2→3→4
nums2 = [3, 2, 1, 0, 4]  # False: always land on index 3 (value 0)

# At index 3 (value 0): no matter how you get here,
# you can't jump further to reach index 4
print('nums1 last index:', len(nums1)-1)
print('nums2 index 3 jump value:', nums2[3])  # 0 = stuck

Greedy: Maximale Reichweite verfolgen

Die entscheidende Greedy-Idee bei Jump Game I: Verwalten Sie max_reach, den bisher am weitesten erreichbaren Index. Aktualisieren Sie bei jedem Index i den Wert mit max_reach = max(max_reach, i + nums[i]). Falls irgendwann i > max_reach gilt, ist der aktuelle Index nicht erreichbar — geben Sie False zurück. Wenn Sie den letzten Index erreichen oder überschreiten, geben Sie True zurück. Dynamische Programmierung oder Backtracking sind nicht erforderlich.

def can_jump(nums):
    max_reach = 0
    for i, jump in enumerate(nums):
        if i > max_reach:      # can't reach index i
            return False
        max_reach = max(max_reach, i + jump)
        if max_reach >= len(nums) - 1:
            return True  # early exit
    return True

print(can_jump([2, 3, 1, 1, 4]))  # True
print(can_jump([3, 2, 1, 0, 4]))  # False
print(can_jump([0]))              # True (already at last index)
print(can_jump([1, 0, 0]))        # False

Jump Game I nachvollziehen

Verfolgen wir [3, 2, 1, 0, 4]: i=0, Sprung=3, max_reach=3. i=1, Sprung=2, max_reach=max(3,3)=3. i=2, Sprung=1, max_reach=max(3,3)=3. i=3, Sprung=0, max_reach=max(3,3)=3. i=4, i=4 > max_reach=3 → geben Sie False zurück. Der Algorithmus erkennt korrekt, dass Index 4 nicht erreichbar ist. Jeder Pfad von Index 0 aus ist gefangen, weil die 0 an Index 3 die max_reach auf 3 begrenzt.

def can_jump_trace(nums):
    max_reach = 0
    for i, jump in enumerate(nums):
        print(f'i={i}, jump={jump}, max_reach before={max_reach}', end='')
        if i > max_reach:
            print(' → UNREACHABLE')
            return False
        max_reach = max(max_reach, i + jump)
        print(f' → max_reach={max_reach}')
    return True

print('Result:', can_jump_trace([3, 2, 1, 0, 4]))

Jump Game II: Minimale Anzahl von Sprüngen

Bei Jump Game II (LeetCode 45) soll die minimale Anzahl von Sprüngen ermittelt werden, um den letzten Index zu erreichen (dieser ist immer erreichbar). Der Greedy-Ansatz verwendet eine Strategie zur Erweiterung des erreichbaren Bereichs: Verwalten Sie die größte Reichweite des aktuellen Sprungs (curr_end) und die größte Reichweite des nächsten Sprungs (farthest). Wenn der Bereich des aktuellen Sprungs ausgeschöpft ist, müssen Sie springen — erhöhen Sie jumps und setzen Sie curr_end = farthest.

def jump(nums):
    n = len(nums)
    if n == 1: return 0  # already at destination
    jumps = 0
    curr_end = 0   # end of current jump's range
    farthest = 0   # farthest reachable in next jump
    for i in range(n - 1):  # don't jump from last index
        farthest = max(farthest, i + nums[i])
        if i == curr_end:    # exhausted current jump range
            jumps += 1
            curr_end = farthest
            if curr_end >= n - 1: break
    return jumps

print(jump([2, 3, 1, 1, 4]))  # 2 (0→1→4)
print(jump([2, 3, 0, 1, 4]))  # 2 (0→1→4)
print(jump([1, 2, 1, 1, 1])) # 3

Jump Game II visualisieren

Betrachten Sie Jump Game II als einen BFS-Durchlauf Ebene für Ebene, jedoch ohne den zusätzlichen Aufwand einer Warteschlange. Jeder Sprung entspricht einer BFS-Ebene. curr_end ist die Grenze der aktuellen Ebene. farthest ist der maximal erreichbare Index der nächsten Ebene. Wenn Sie die aktuelle Ebene vollständig durchlaufen haben (i == curr_end), steht die Grenze der nächsten Ebene fest und Sie müssen den Sprungzähler erhöhen. Dies ist ein BFS auf einem impliziten Graphen mit einer Laufzeit von O(n) und einem Speicherbedarf von O(1).

def jump_traced(nums):
    n = len(nums)
    jumps = curr_end = farthest = 0
    for i in range(n - 1):
        farthest = max(farthest, i + nums[i])
        print(f'i={i}: farthest={farthest}, curr_end={curr_end}')
        if i == curr_end:
            jumps += 1
            curr_end = farthest
            print(f'  → JUMP #{jumps}, new range ends at {curr_end}')
            if curr_end >= n - 1: break
    return jumps

print('Min jumps:', jump_traced([2, 3, 1, 1, 4]))

Warum Greedy bei Jump Game II korrekt ist

Warum liefert Greedy (immer die größtmögliche Reichweite zu nutzen) die minimale Anzahl von Sprüngen? Austauschargument: Angenommen, die optimale Lösung führt einen Sprung aus, der nicht den am weitesten entfernten Punkt erreicht. Wir können diesen Sprung immer bis zu farthest erweitern, ohne zusätzliche Kosten zu verursachen — es bleibt ein einziger Sprung. Indem wir bei jedem Sprung stets die maximale Reichweite nutzen, stellen wir die minimale erforderliche Sprunganzahl sicher. Eine Lösung, die pro Sprung eine geringere Reichweite nutzt, kann nicht besser sein und würde mehr Sprünge benötigen, um dieselbe Strecke zurückzulegen.

# Correctness verification: compare to BFS
from collections import deque

def jump_bfs(nums):
    n = len(nums)
    if n == 1: return 0
    visited = [False] * n
    visited[0] = True
    queue = deque([0])
    level = 0
    while queue:
        level += 1
        for _ in range(len(queue)):
            pos = queue.popleft()
            for j in range(1, nums[pos] + 1):
                nxt = pos + j
                if nxt >= n - 1: return level
                if not visited[nxt]:
                    visited[nxt] = True
                    queue.append(nxt)
    return -1

# Both should give same results
for nums in [[2,3,1,1,4],[2,3,0,1,4],[1,2,1,1,1]]:
    print(jump(nums), '==', jump_bfs(nums))

DP-Alternative für Jump Game II

Eine DP-Lösung: dp[i] = minimale Anzahl von Sprüngen, um Index i zu erreichen. Aktualisieren Sie für jede Position j alle erreichbaren Positionen: dp[j+k] = min(dp[j+k], dp[j]+1) für k in 1..nums[j]. Dies benötigt O(n × max_jump) Zeit und O(n) Speicher — deutlich mehr als der Greedy-Ansatz mit O(n). Der Greedy-Ansatz ist hier überlegen; die DP-Lösung wird zum Vergleich gezeigt, um zu veranschaulichen, wie Greedy die innere Schleife vermeiden kann.

def jump_dp(nums):
    n = len(nums)
    dp = [float('inf')] * n
    dp[0] = 0
    for j in range(n):
        for k in range(1, nums[j] + 1):
            if j + k < n:
                dp[j+k] = min(dp[j+k], dp[j] + 1)
    return dp[n-1]

print(jump_dp([2, 3, 1, 1, 4]))  # 2
print(jump_dp([1, 2, 1, 1, 1]))  # 3

# Greedy is O(n), DP is O(n * max_jump)
# For large inputs with big jump values, greedy is much faster

Jump Game III: Index 0 erreichen

Jump Game III (LeetCode 1306): Starten Sie an einem vorgegebenen Index. Von Index i aus springen Sie zu i + nums[i] oder i - nums[i]. Können Sie einen beliebigen Index mit dem Wert 0 erreichen? Dies ist ein Erreichbarkeitsproblem (BFS/DFS), kein Minimierungsproblem — Greedy ist hier nicht anwendbar. Verwenden Sie BFS mit einer Menge besuchter Indizes, um Zyklen zu vermeiden. Laufzeit: O(n).

from collections import deque

def can_reach(arr, start):
    n = len(arr)
    visited = set()
    queue = deque([start])
    while queue:
        idx = queue.popleft()
        if arr[idx] == 0: return True
        if idx in visited: continue
        visited.add(idx)
        for nxt in [idx + arr[idx], idx - arr[idx]]:
            if 0 <= nxt < n and nxt not in visited:
                queue.append(nxt)
    return False

print(can_reach([4,2,3,0,3,1,2], 5))  # True (5→4→1→3, arr[3]=0)
print(can_reach([3,0,2,1,2], 2))      # False (can't reach index 1, arr[1]=0)

Jump Game VII: Erreichbarkeit mit einem Bereich

Jump Game VII (LeetCode 1871): Können Sie eine Binärzeichenkette durchlaufen, indem Sie von Index 0 zum letzten Index springen, wobei Sie von Position i zu jeder '0' in [i+minJump, i+maxJump] springen können? Verwenden Sie eine Sliding-Window-Summe über dem Array der erreichbaren Positionen. Verwalten Sie eine Präfixsumme der erreichbaren Positionen. Eine Position j ist erreichbar, wenn es eine erreichbare Position in [j-maxJump, j-minJump] gibt.

def can_reach_vii(s, min_jump, max_jump):
    n = len(s)
    reach = [False] * n
    reach[0] = True
    pre = [0] * (n + 1)  # prefix sum of reachable positions
    pre[1] = 1
    for j in range(1, n):
        # Window sum: any reachable position in [j-maxJump, j-minJump]?
        lo = max(0, j - max_jump)
        hi = max(0, j - min_jump + 1)
        window_sum = pre[hi] - pre[lo]
        if s[j] == '0' and window_sum > 0:
            reach[j] = True
        pre[j+1] = pre[j] + (1 if reach[j] else 0)
    return reach[n-1]

print(can_reach_vii('011010', 2, 3))  # True
print(can_reach_vii('01101110', 2, 3))  # False

Greedy- und BFS-Lösungen vergleichen

Für Jump Game II gibt es zwei gleichwertige Ansätze mit O(n): die Greedy-Erweiterung des erreichbaren Bereichs und der BFS-Durchlauf nach Ebenen. Der Greedy-Ansatz benötigt O(1) Speicher (keine Warteschlange), während BFS O(n) für die Menge der besuchten Indizes benötigt. In einem Vorstellungsgespräch wird Greedy wegen des geringeren Speicherbedarfs bevorzugt. BFS lässt sich jedoch zunächst leichter herleiten — wenn Sie die Greedy-Lösung nicht erkennen, implementieren Sie zunächst BFS, um eine funktionierende Lösung zu erhalten, und optimieren Sie sie anschließend. Beide Ansätze berechnen die minimale Anzahl von Sprüngen korrekt.

# Both approaches are O(n) time
# Greedy: O(1) space — preferred in interviews
# BFS: O(n) space — easier to derive

# Greedy advantage: no auxiliary data structures
def jump_greedy(nums):
    n, jumps, curr, far = len(nums), 0, 0, 0
    for i in range(n-1):
        far = max(far, i+nums[i])
        if i == curr: jumps += 1; curr = far
    return jumps

# BFS equivalence: each level = one jump
from collections import deque
def jump_bfs(nums):
    n = len(nums)
    if n == 1: return 0
    q, visited, level = deque([0]), {0}, 0
    while q:
        level += 1
        for _ in range(len(q)):
            pos = q.popleft()
            for j in range(1, nums[pos]+1):
                nxt = pos + j
                if nxt >= n-1: return level
                if nxt not in visited: visited.add(nxt); q.append(nxt)
    return -1

nums = [2,3,1,1,4]
print(jump_greedy(nums), '==', jump_bfs(nums))  # both 2

Zusammenfassung der Komplexität von Jump Game

Zusammenfassung der Komplexität der verschiedenen Jump-Game-Varianten: Jump I (Erreichbarkeit): O(n) Zeit, O(1) Speicher. Jump II (Greedy für minimale Sprunganzahl): O(n) Zeit, O(1) Speicher. Jump II (BFS): O(n) Zeit, O(n) Speicher. Jump II (DP): O(n × max_jump) Zeit, O(n) Speicher. Jump III (BFS/DFS): O(n) Zeit, O(n) Speicher für die besuchten Indizes. Jump VII (Sliding Window): O(n) Zeit, O(n) Speicher. Präsentieren Sie in Vorstellungsgesprächen für Jump I und II stets die Greedy-Lösung mit O(n) Zeit und O(1) Speicher.

# Comparison: all versions on the same input
nums = [2, 3, 1, 1, 4]

# Jump I
def can_jump(nums):
    mr = 0
    for i, j in enumerate(nums):
        if i > mr: return False
        mr = max(mr, i+j)
    return True

# Jump II greedy O(n) O(1)
def jump_min(nums):
    n, jumps, curr, far = len(nums), 0, 0, 0
    for i in range(n-1):
        far = max(far, i+nums[i])
        if i == curr:
            jumps += 1; curr = far
            if curr >= n-1: break
    return jumps

print('Can reach:', can_jump(nums))    # True
print('Min jumps:', jump_min(nums))    # 2
print('Complexity: O(n) time, O(1) space')

Kurztest

Testen Sie Ihr Verständnis der Konzepte aus Data Structures & Algorithms — Coding Interview Prep in dieser Lektion.

Zusammenfassung der Lektion

In dieser Lektion haben Sie gelernt: Jump Game I verwendet die Greedy-Verfolgung von max_reach, um die Erreichbarkeit mit O(n) Zeit und O(1) Speicher zu bestimmen, Jump Game II verwendet mit curr_end und farthest eine Erweiterung des erreichbaren Bereichs, um die minimale Sprunganzahl mit O(n) Zeit und O(1) Speicher zu zählen, und die Greedy-Erweiterung des erreichbaren Bereichs entspricht einem BFS-Durchlauf Ebene für Ebene ohne den zusätzlichen Aufwand einer Warteschlange. Als Nächstes wenden wir Greedy-Überlegungen auf die Abkühlphase beim Task Scheduler und die Probleme zur Erreichbarkeit im Kreis beim Gas Station an.

Häufig gestellte Fragen

Ist die Lektion „Jump Game I und II“ kostenlos?

Ja — der vollständige Text von „Jump Game I und II“ ist hier im Web kostenlos zu lesen. Um sie interaktiv zu üben (integrierter Code-Editor und 24/7 KI-Tutor) und den Rest des Coding Interview Prep-Kurses freizuschalten, upgrade auf CoddyKit PRO. Der Coding Interview Prep-Kurs umfasst insgesamt 4 Lektionen.

Was lerne ich in „Jump Game I und II“?

Bestimmen Sie Erreichbarkeit und minimale Sprunganzahl mithilfe eines Greedy-Ansatzes zur Bereichserweiterung, der keine dynamische Programmierung benötigt. Du übst Coding Interview Prep mit praktischem Code, den du direkt im Browser ausführst, und ein 24/7 KI-Tutor beantwortet deine Fragen während du die Lektion bearbeitest.

Brauche ich Erfahrung, um Coding Interview Prep zu starten?

Keine Vorkenntnisse erforderlich. Coding Interview Prep auf CoddyKit ist für Anfänger bis fortgeschrittene Lernende strukturiert, sodass du hier starten oder von Anfang an beginnen und in deinem eigenen Tempo voranschreiten kannst. Dies ist Lektion 3 von 4.

Wie lange dauert die Lektion „Jump Game I und II“?

Die meisten CoddyKit-Lektionen dauern etwa 5–10 Minuten. Jede ist kompakt und interaktiv, sodass du stetig Fortschritte machst und genau dort weitermachst, wo du aufgehört hast – im Web und in der App.

Kann ich in dieser Coding Interview Prep-Lektion Code schreiben und ausführen?

Ja. Jede Coding Interview Prep-Lektion enthält einen integrierten Code-Editor, sodass du echten Code direkt in deinem Browser schreibst und ausführst und sofort KI-Feedback erhältst — ohne lokale Einrichtung erforderlich.

Alle Lektionen in diesem Kurs

  1. Greedy vs. dynamische Programmierung: Wann wird was verwendet?
  2. Intervallplanung und Zusammenführen
  3. Jump Game I und II
  4. Task Scheduler und Gas Station
← Zurück zu Coding Interview Prep