Coding Interview Prep · Ders

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.

3. ders / 413 adım

Sıçrama Oyunu I ve II, CoddyKit'te ücretsiz bir Coding 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, Coding Interview Prep öğrenme yolunun bir parçasıdır ve ilerlemeniz web ve CoddyKit uygulaması arasında senkronize olur. Coding 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 = stuck

Aç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]))        # False

Sıç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])) # 3

Sıç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 faster

Sıç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))  # False

Aç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 2

Sıç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.

Başlamak ücretsiz

Yapay zeka eğitmeniyle Coding Interview Prep öğ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
90
Dersler
360

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 Coding Interview Prep kursunun geri kalanını açmak için CoddyKit PRO'ya yükselt. Coding 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. Coding 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.

Coding Interview Prep öğrenmeye başlamak için deneyim gerekli mi?

Önceden deneyim gerekmez. CoddyKit'te Coding 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 Coding Interview Prep dersinde kod yazıp çalıştırabilir miyim?

Evet. Her Coding 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

  1. Açgözlü Yaklaşım mı DP mi: Hangisi Ne Zaman Kullanılır
  2. Aralık Çizelgeleme ve Birleştirme
  3. Sıçrama Oyunu I ve II
  4. Görev Çizelgeleyici ve Benzin İstasyonu
← Coding Interview Prep Sayfasına Dön