Sıçrama Oyunu I ve II
DP gerektirmeyen açgözlü aralık genişletme yaklaşımını kullanarak erişilebilirliği ve minimum sıçrama sayısını belirleyin.
Sıçrama Oyunu I ve II, CoddyKit'te ücretsiz bir DSA Interview Prep dersidir. Bu, 4 dersinin 3. dersidir. Aşağıdan dersin tamamını ücretsiz okuyabilir, sonra tarayıcıda yerleşik kod editörü ve 7/24 yapay zeka koçu ile uygulamalı olarak pratik yapabilirsin. Bu, DSA Interview Prep öğrenme yolunun bir parçasıdır ve ilerlemeniz web ve CoddyKit uygulaması arasında senkronize olur. DSA Interview Prep kursu toplamda 4 dersten oluşur.
Sıçrama Oyunu I: Sona Ulaşabilir misiniz?
Sıçrama Oyunu I (LeetCode 55): nums[i] değerinin i dizininden yapılabilecek maksimum sıçrama uzunluğu olduğu bir dizi verildiğinde, 0 dizininden başlayarak son dizine ulaşıp ulaşamayacağınızı belirleyin. [2, 3, 1, 1, 4] için sona ulaşabilirsiniz (2→3 sıçrayın, ardından 3 sizi sona ulaştırır). [3, 2, 1, 0, 4] için ulaşamazsınız (her zaman sıçrama uzunluğu 0 olan 0'a inersiniz). Açgözlü çözüm O(n) zamanda çalışır.
# 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 = stuckAçgözlü Yaklaşım: Maksimum Erişimi İzleme
Sıçrama Oyunu I için açgözlü yaklaşımın temel fikri şudur: şimdiye kadar erişilebilen en uzak dizini gösteren max_reach değerini koruyun. Her i dizininde max_reach = max(max_reach, i + nums[i]) güncellemesini yapın. Herhangi bir noktada i > max_reach olursa mevcut dizine erişilemiyordur — False döndürün. Son dizine ulaşırsak veya onu geçersek True döndürün. DP ya da geri izleme gerekmez.
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])) # FalseSıçrama Oyunu I'i İzleme
[3, 2, 1, 0, 4] dizisini izleyin: 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 → False döndürülür. Algoritma, 4 dizinine erişilemediğini doğru biçimde belirler. 0 dizininden başlayan her yol tuzağa düşer; çünkü 3 dizinindeki 0, max_reach değerini 3 ile sınırlar.
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]))Sıçrama Oyunu II: Minimum Sıçramalar
Sıçrama Oyunu II (LeetCode 45), son dizine ulaşmak için gereken minimum sıçrama sayısını sorar (sona her zaman ulaşılabilir). Açgözlü yaklaşım bir aralık genişletme stratejisi kullanır: mevcut sıçramanın erişebileceği en uzak konumu (curr_end) ve bir sonraki sıçramanın erişebileceği en uzak konumu (farthest) koruyun. Mevcut sıçramanın aralığını tükettiğinizde bir sıçrama yapmanız gerekir — jumps değerini artırın ve curr_end = farthest atamasını yapın.
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])) # 3Sıçrama Oyunu II'yi Görselleştirme
Sıçrama Oyunu II'yi, kuyruk yükü olmayan seviye seviye BFS yaklaşımı olarak düşünün. Her sıçrama bir BFS seviyesine karşılık gelir. curr_end mevcut seviyenin sınırıdır. farthest ise bir sonraki seviyede erişilebilecek maksimum dizindir. Mevcut seviyeyi taramayı bitirdiğinizde (i == curr_end), bir sonraki seviyenin sınırını belirlemiş olursunuz ve sıçrama sayısını artırmanız gerekir. Bu, O(n) zamanda ve O(1) alanda örtük bir grafik üzerinde yapılan BFS'tir.
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]))Sıçrama Oyunu II İçin Açgözlü Yaklaşım Neden Doğru?
Açgözlü yaklaşım (her zaman en uzak noktaya kadar genişletmek) neden minimum sıçrama sayısını verir? Değiş tokuş argümanı kullanalım: En iyi çözümün en uzak noktaya ulaşmayan bir sıçrama yaptığını varsayalım. Bu sıçramayı, ek bir maliyet olmadan farthest konumuna ulaşacak şekilde her zaman genişletebiliriz — hâlâ tek bir sıçramadır. Her sıçramada maksimum aralığı kullanarak gereken minimum sıçrama sayısını garanti ederiz. Her sıçramada daha kısa bir aralık kullanan hiçbir çözüm daha iyi sonuç veremez; aynı mesafeyi kapatmak için daha fazla sıçramaya ihtiyaç duyar.
# 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))Sıçrama Oyunu II İçin DP Alternatifi
Bir DP çözümü: dp[i] = i dizinine ulaşmak için gereken minimum sıçrama sayısı. Her j konumu için erişilebilen tüm konumları güncelleyin: dp[j+k] = min(dp[j+k], dp[j]+1); burada k, 1..nums[j] aralığındadır. Bu çözüm O(n × max_jump) zamanda ve O(n) alanda çalışır; O(n) zamanlı açgözlü çözümden çok daha yavaştır. Burada açgözlü çözüm üstündür; DP, açgözlü yaklaşımın iç döngüyü nasıl ortadan kaldırabildiğini göstermek için karşılaştırma amacıyla verilmiştir.
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 fasterSıçrama Oyunu III: Sıfır Dizinine Ulaşma
Sıçrama Oyunu III (LeetCode 1306): verilen bir dizinden başlayın; i dizininden i + nums[i] veya i - nums[i] dizinine sıçrayın. Değeri 0 olan herhangi bir dizine ulaşabilir misiniz? Bu bir eniyileme problemi değil, erişilebilirlik problemidir (BFS/DFS) — açgözlü yaklaşım uygulanamaz. Döngüleri önlemek için ziyaret edilmiş kümesiyle BFS kullanın. Zaman karmaşıklığı: 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)Sıçrama Oyunu VII: Aralık İçinde Erişilebilirlik
Sıçrama Oyunu VII (LeetCode 1871): i konumundan [i+minJump, i+maxJump] aralığındaki herhangi bir '0'a sıçrayarak 0 dizininden son dizine ikili bir dizede ilerleyebilir misiniz? Erişilebilirlik dizisi üzerinde kayan pencere toplamı kullanın. Erişilebilir konumların önek toplamını koruyun; j konumuna, [j-maxJump, j-minJump] aralığında erişilebilir bir konum varsa erişilebilir.
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)) # FalseAçgözlü ve BFS Çözümlerinin Karşılaştırılması
Sıçrama Oyunu II için O(n) zamanlı iki eşdeğer yaklaşım vardır: açgözlü aralık genişletme ve BFS seviye geçişi. Açgözlü yaklaşım O(1) alan kullanır (kuyruk yoktur), BFS ise ziyaret edilmiş kümesi için O(n) alan kullanır. Bir mülakatta, alan verimliliği nedeniyle açgözlü yaklaşım tercih edilir. Bununla birlikte BFS'yi önce türetmek daha kolaydır — açgözlü çözümü görmekte zorlanırsanız çalışan bir çözüm elde etmek için BFS'yi kodlayın, ardından iyileştirin. Her ikisi de minimum sıçrama sayısını doğru biçimde hesaplar.
# 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 2Sıçrama Oyunu Karmaşıklık Özeti
Sıçrama Oyunu çeşitleri için karmaşıklık özeti: Sıçrama I (erişilebilirlik): O(n) zaman, O(1) alan. Sıçrama II (minimum sıçrama, açgözlü): O(n) zaman, O(1) alan. Sıçrama II (BFS): O(n) zaman, O(n) alan. Sıçrama II (DP): O(n × max_jump) zaman, O(n) alan. Sıçrama III (BFS/DFS): O(n) zaman, ziyaret edilenler için O(n) alan. Sıçrama VII (kayan pencere): O(n) zaman, O(n) alan. Mülakatlarda Sıçrama Oyunu I ve II için her zaman O(n) zamanlı O(1) alanlı açgözlü çözümü sunun.
# 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')Hızlı Kontrol
Bu dersteki Veri Yapıları ve Algoritmalar — Kodlama Mülakatına Hazırlık kavramlarını anlayıp anlamadığınızı test edin.
Ders Özeti
Bu derste şunları öğrendiniz: Sıçrama Oyunu I'in erişilebilirliği O(n) zamanda ve O(1) alanda belirlemek için açgözlü max_reach takibi kullandığını, Sıçrama Oyunu II'nin O(n) zamanda ve O(1) alanda minimum sıçramaları saymak için curr_end ve farthest ile aralık genişletme kullandığını ve açgözlü aralık genişletmenin kuyruk yükü olmayan seviye seviye BFS'ye eşdeğer olduğunu. Sırada, açgözlü akıl yürütmeyi Görev Zamanlayıcı'nın soğuma süresine ve Benzin İstasyonu'nun dairesel uygulanabilirlik problemlerine uygulayacağız.
Yapay zeka eğitmeniyle Python öğren — ücretsiz
Tarayıcında gerçek kod yaz ve çalıştır, 7/24 yapay zeka eğitmeninden anında yardım al; web'de ya da uygulamada kaldığın yerden devam et.
- Kurslar
- 30
- Dersler
- 120
Sıkça Sorulan Sorular
“Sıçrama Oyunu I ve II” dersi ücretsiz mi?
Evet — “Sıçrama Oyunu I ve II” dersin tüm metni burada web'de ücretsiz olarak okunabilir. Etkileşimli olarak pratik yapmak (yerleşik kod editörü ve 7/24 yapay zeka koçu) ve DSA Interview Prep kursunun geri kalanını açmak için CoddyKit PRO'ya yükselt. DSA Interview Prep kursu toplamda 4 dersten oluşur.
“Sıçrama Oyunu I ve II” dersinde ne öğreneceğim?
DP gerektirmeyen açgözlü aralık genişletme yaklaşımını kullanarak erişilebilirliği ve minimum sıçrama sayısını belirleyin. DSA Interview Prep ile uygulamalı kodu tarayıcıda doğrudan çalıştırarak pratik yaparsın ve 7/24 yapay zeka koçu dersi çalışırken sorularını yanıtlar.
DSA Interview Prep öğrenmeye başlamak için deneyim gerekli mi?
Önceden deneyim gerekmez. CoddyKit'te DSA Interview Prep, başlangıçtan ileri seviyeye kadar yapılandırıldığı için buradan başlayabilir veya başından başlayıp kendi hızında ilerleme yapabilirsin. Bu, 4 dersinin 3. dersidir.
“Sıçrama Oyunu I ve II” dersi ne kadar sürer?
Çoğu CoddyKit dersi yaklaşık 5–10 dakika sürer. Her biri kısa ve etkileşimli olduğu için sabit ilerleme yaparsın ve web ile uygulama arasında tam olarak bıraktığın yerden devam edebilirsin.
Bu DSA Interview Prep dersinde kod yazıp çalıştırabilir miyim?
Evet. Her DSA Interview Prep dersi yerleşik bir kod editörü içerir, bu sayede tarayıcıda gerçek kod yazıp çalıştırabilir ve anlık yapay zeka geri bildirimi alırsın — yerel kurulum gerekli değildir.
Bu kursun tüm dersleri
- Açgözlü Yaklaşım mı DP mi: Hangisi Ne Zaman Kullanılır
- Aralık Çizelgeleme ve Birleştirme
- Sıçrama Oyunu I ve II
- Görev Çizelgeleyici ve Benzin İstasyonu