DSA Interview Prep · Lektion

Jump Game I och II

Avgör nåbarhet och minsta antal hopp med en girig metod som utökar räckvidden och undviker behovet av DP.

Lektion 3 av 413 steg

Jump Game I och II är en gratis lektion i DSA Interview Prep på CoddyKit. Detta är lektion 3 av 4. Du kan läsa vilka 3 lektioner som helst i den här lärvägen kostnadsfritt i sin helhet – därefter låser CoddyKit PRO upp alla lektioner, plus praktisk övning med en inbyggd kodredigerare och en AI-lärare dygnet runt. Den ingår i lärvägen för DSA Interview Prep, och Era framsteg synkroniseras mellan webben och CoddyKit-appen. Kursen i DSA Interview Prep innehåller totalt 4 lektioner.

Jump Game I: Går det att nå slutet?

Jump Game I (LeetCode 55): givet en array där nums[i] anger den maximala hopplängden från index i, avgör om ni kan nå det sista indexet med start från index 0. För [2, 3, 1, 1, 4] kan ni nå slutet (hoppa 2→3, sedan tar 3 er till slutet). För [3, 2, 1, 0, 4] går det inte (ni landar alltid på 0, som har hopplängden 0). En girig lösning körs på 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

Girig metod: följ maximal räckvidd

Den giriga insikten för Jump Game I är att hålla reda på max_reach, det längst bort nåbara indexet hittills. Uppdatera max_reach = max(max_reach, i + nums[i]) vid varje index i. Om ni någon gång får i > max_reach är det aktuella indexet inte nåbart — returnera False. Om ni når eller passerar det sista indexet, returnera True. Ingen DP eller backtracking behövs.

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

Spåra Jump Game I

Spåra [3, 2, 1, 0, 4]: i=0, jump=3, max_reach=3. i=1, jump=2, max_reach=max(3,3)=3. i=2, jump=1, max_reach=max(3,3)=3. i=3, jump=0, max_reach=max(3,3)=3. i=4, i=4 > max_reach=3 → return False. Algoritmen identifierar korrekt att index 4 inte är nåbart. Alla vägar från index 0 fastnar, eftersom 0 på index 3 begränsar max_reach till 3.

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: Minsta antal hopp

Jump Game II (LeetCode 45) handlar om att hitta det minsta antalet hopp för att nå det sista indexet (som alltid är nåbart). Den giriga metoden använder en strategi med räckviddsutvidgning: håll reda på det aktuella hoppets maximala räckvidd (curr_end) och nästa hopps maximala räckvidd (farthest). När ni har gått igenom det aktuella hoppets räckvidd måste ni hoppa — öka jumps och sätt 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

Visualisering av Jump Game II

Tänk på Jump Game II som en BFS nivå för nivå-metod utan kostnaden för en kö. Varje hopp motsvarar en BFS-nivå. curr_end är gränsen för den aktuella nivån. farthest är det största index som kan nås på nästa nivå. När ni har gått igenom den aktuella nivån (i == curr_end) har ni bestämt nästa nivås gräns och måste öka hoppantalet. Detta är BFS på en implicit graf med tidskomplexiteten O(n) och minneskomplexiteten 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]))

Varför den giriga metoden är korrekt för Jump II

Varför ger den giriga metoden (att alltid utöka till längst möjliga räckvidd) minsta antal hopp? Bytesargument: anta att den optimala lösningen gör ett hopp som inte når den längst möjliga punkten. Vi kan alltid utöka hoppet så att det når farthest utan någon extra kostnad — det är fortfarande ett enda hopp. Genom att alltid välja maximal räckvidd per hopp garanterar vi det minsta antalet hopp som behövs. En lösning som tar kortare räckvidd per hopp kan inte göra bättre ifrån sig och skulle behöva fler hopp för att täcka samma sträcka.

# 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-alternativ för Jump Game II

En DP-lösning: dp[i] = minsta antalet hopp för att nå index i. För varje position j uppdateras alla nåbara positioner: dp[j+k] = min(dp[j+k], dp[j]+1) för k i 1..nums[j]. Detta körs på O(n × max_jump) tid och använder O(n) minnesutrymme — betydligt långsammare än den giriga metoden på O(n). Den giriga metoden är överlägsen här; DP visas som jämförelse för att illustrera hur den giriga metoden kan undvika den inre loopen.

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: Nå index noll

Jump Game III (LeetCode 1306): börja på ett givet index; från index i kan ni hoppa till i + nums[i] eller i - nums[i]. Kan ni nå något index med värdet 0? Detta är ett nåbarhetsproblem (BFS/DFS), inte ett minimeringsproblem — girig metod är inte tillämplig. Använd BFS med en mängd besökta index för att undvika cykler. Tid: 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: Nåbarhet med intervall

Jump Game VII (LeetCode 1871): kan ni gå igenom en binär sträng genom att hoppa från index 0 till det sista indexet, där ni från position i kan hoppa till vilket '0' som helst i [i+minJump, i+maxJump]? Använd en glidande fönstersumma över nåbarhetsarrayen. Håll reda på en prefixsumma av nåbara positioner; en position j är nåbar om det finns en nåbar position i [j-maxJump, j-minJump].

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

Jämförelse mellan giriga och BFS-lösningar

Jump Game II har två likvärdiga O(n)-metoder: girig räckviddsutvidgning och BFS-genomgång nivå för nivå. Den giriga metoden använder O(1) minnesutrymme (ingen kö), medan BFS använder O(n) för mängden besökta index. I en intervju föredras den giriga metoden på grund av dess minneseffektivitet. BFS är dock enklare att härleda först — om ni har svårt att se den giriga lösningen kan ni koda BFS för att få en fungerande lösning och sedan optimera den. Båda metoderna beräknar korrekt det minsta antalet hopp.

# 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

Sammanfattning av komplexitet för Jump Game-varianter

Sammanfattning av komplexiteten för olika Jump Game-varianter: Jump I (nåbarhet): O(n) tid, O(1) minnesutrymme. Jump II (girig metod för minsta antal hopp): O(n) tid, O(1) minnesutrymme. Jump II (BFS): O(n) tid, O(n) minnesutrymme. Jump II (DP): O(n × max_jump) tid, O(n) minnesutrymme. Jump III (BFS/DFS): O(n) tid, O(n) minnesutrymme för besökta index. Jump VII (glidande fönster): O(n) tid, O(n) minnesutrymme. I intervjuer bör ni alltid presentera den giriga O(n)-lösningen med O(1) minnesutrymme för Jump I och II.

# 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')

Snabbtest

Testa era kunskaper om begreppen inom Data Structures & Algorithms — Coding Interview Prep från den här lektionen.

Sammanfattning av lektionen

I den här lektionen har ni lärt er: Jump Game I använder girig spårning av max_reach för att avgöra nåbarhet på O(n) tid och med O(1) minnesutrymme, Jump Game II använder räckviddsutvidgning med curr_end och farthest för att räkna minsta antalet hopp på O(n) tid och med O(1) minnesutrymme, samt att girig räckviddsutvidgning motsvarar BFS nivå för nivå utan kostnaden för kön. Nästa steg är att tillämpa girigt resonemang på Task Scheduler-problemet med cooldown och Gas Station-problemen om cirkulär genomförbarhet.

Gratis att börja

Lär dig Python med en AI-lärare – gratis

Skriv och kör riktig kod i webbläsaren, få omedelbar hjälp av en AI-lärare dygnet runt och fortsätt där du slutade – på webben eller i appen.

Kurser
30
Lektioner
120

Vanliga frågor

Är lektionen ”Jump Game I och II” gratis?

Ja – du kan läsa vilka 3 lektioner som helst i lärvägen DSA Interview Prep, inklusive ”Jump Game I och II”, kostnadsfritt i sin helhet här på webben. Därefter låser CoddyKit PRO upp alla lektioner, plus interaktiv övning med en inbyggd kodredigerare och en AI-lärare dygnet runt. Kursen i DSA Interview Prep innehåller totalt 4 lektioner.

Vad lär jag mig i ”Jump Game I och II”?

Avgör nåbarhet och minsta antal hopp med en girig metod som utökar räckvidden och undviker behovet av DP. Ni övar på DSA Interview Prep med praktisk kod som körs direkt i webbläsaren, medan en AI-handledare som är tillgänglig dygnet runt svarar på Era frågor under lektionen.

Behöver jag någon erfarenhet för att börja lära mig DSA Interview Prep?

Du behöver inga förkunskaper. Utbildningen i DSA Interview Prep på CoddyKit är upplagd för allt från nybörjare till avancerade elever, så att du kan börja här eller från början och gå fram i din egen takt. Detta är lektion 3 av 4.

Hur lång tid tar lektionen ”Jump Game I och II”?

De flesta CoddyKit-lektioner tar cirka 5–10 minuter. Varje lektion är kort och interaktiv, så att du gör stadiga framsteg och kan fortsätta precis där du slutade – på webben eller i appen.

Kan jag skriva och köra kod i den här DSA Interview Prep-lektionen?

Ja. Varje DSA Interview Prep-lektion innehåller en inbyggd kodredigerare, så att du kan skriva och köra riktig kod direkt i webbläsaren och få omedelbar AI-feedback – utan lokal installation.

Alla lektioner i den här kursen

  1. Giriga algoritmer eller DP: när används vad
  2. Intervallschemaläggning och sammanslagning
  3. Jump Game I och II
  4. Task Scheduler och Gas Station
← Tillbaka till DSA Interview Prep