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.
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 = stuckGirig 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])) # FalseSpå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])) # 3Visualisering 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 fasterJump 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)) # FalseJä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 2Sammanfattning 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.
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
- Giriga algoritmer eller DP: när används vad
- Intervallschemaläggning och sammanslagning
- Jump Game I och II
- Task Scheduler och Gas Station