0Pricing
DSA Interview Prep · Leçon

Jeu des sauts I et II

Déterminez l’accessibilité et le nombre minimal de sauts à l’aide d’une approche gloutonne d’élargissement de plage, sans recourir à DP.

Jeu des sauts I et II est une leçon DSA Interview Prep gratuite sur CoddyKit. Ceci est la leçon 3 sur 4. Tu peux lire la leçon complète ci-dessous gratuitement — puis la pratiquer en direct dans le navigateur avec un éditeur de code intégré et un tuteur IA 24/7. Elle fait partie du parcours d'apprentissage DSA Interview Prep, et ta progression se synchronise sur le web et l'application CoddyKit. Le cours DSA Interview Prep comprend 4 leçons au total.

Jeu de sauts I : pouvez-vous atteindre la fin ?

Jeu de sauts I (LeetCode 55) : étant donné un tableau dans lequel nums[i] représente la longueur maximale du saut depuis l’indice i, déterminez si vous pouvez atteindre le dernier indice en partant de l’indice 0. Pour [2, 3, 1, 1, 4], vous pouvez atteindre la fin (un saut de 2 vous amène à 3, puis 3 vous permet d’atteindre la fin). Pour [3, 2, 1, 0, 4], vous ne le pouvez pas (vous atterrissez toujours sur 0, dont la longueur de saut est 0). Une solution gloutonne s’exécute en 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

Approche gloutonne : suivre la portée maximale

L’idée gloutonne de Jeu de sauts I consiste à maintenir max_reach, le plus grand indice accessible jusqu’à présent. À chaque indice i, mettez à jour max_reach = max(max_reach, i + nums[i]). Si, à un moment donné, i > max_reach, l’indice actuel est inaccessible — renvoyez False. Si nous atteignons ou dépassons le dernier indice, renvoyez True. Aucun DP ni retour arrière n’est nécessaire.

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

Tracer Jeu de sauts I

Tracez [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. L’algorithme identifie correctement que l’indice 4 est inaccessible. Chaque chemin depuis l’indice 0 est bloqué, car le 0 à l’indice 3 limite max_reach à 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]))

Jeu de sauts II : nombre minimal de sauts

Jeu de sauts II (LeetCode 45) demande le nombre minimal de sauts pour atteindre le dernier indice, qui est toujours accessible. L’approche gloutonne utilise une stratégie d’extension de portée : maintenez la portée maximale du saut actuel (curr_end) et celle du saut suivant (farthest). Lorsque vous avez épuisé la portée du saut actuel, vous devez effectuer un saut — incrémentez jumps et définissez 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

Visualiser Jeu de sauts II

Considérez Jeu de sauts II comme une approche BFS niveau par niveau, sans le coût supplémentaire de la file. Chaque saut correspond à un niveau de BFS. curr_end est la limite du niveau actuel. farthest est le plus grand indice accessible au niveau suivant. Lorsque vous avez fini de parcourir le niveau actuel (i == curr_end), vous avez déterminé la limite du niveau suivant et devez incrémenter le nombre de sauts. Il s’agit d’un BFS sur un graphe implicite, en O(n) en temps et O(1) en espace.

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]))

Pourquoi l’approche gloutonne est correcte pour Jeu de sauts II

Pourquoi l’approche gloutonne, qui étend toujours la portée jusqu’au point le plus éloigné, donne-t-elle le nombre minimal de sauts ? Argument d’échange : supposons que la solution optimale effectue un saut qui n’atteint pas le point le plus éloigné. Nous pouvons toujours étendre ce saut jusqu’à farthest sans coût supplémentaire : il s’agit toujours d’un seul saut. En prenant toujours la portée maximale à chaque saut, nous garantissons le nombre minimal de sauts nécessaires. Toute solution qui parcourt une distance moindre à chaque saut ne peut pas faire mieux et aurait besoin de davantage de sauts pour couvrir la même distance.

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

Alternative avec DP pour Jeu de sauts II

Une solution avec DP : dp[i] = nombre minimal de sauts pour atteindre l’indice i. Pour chaque position j, mettez à jour toutes les positions accessibles : dp[j+k] = min(dp[j+k], dp[j]+1) pour k dans 1..nums[j]. Cette solution s’exécute en O(n × max_jump) en temps et utilise O(n) en espace — elle est donc beaucoup plus lente que l’approche gloutonne en O(n). L’approche gloutonne est préférable ici ; la DP est présentée à titre de comparaison, pour montrer comment l’approche gloutonne peut éviter la boucle interne.

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

Jeu de sauts III : atteindre l’indice zéro

Jeu de sauts III (LeetCode 1306) : partez d’un indice donné ; depuis l’indice i, sautez vers i + nums[i] ou i - nums[i]. Pouvez-vous atteindre un indice dont la valeur est 0 ? Il s’agit d’un problème d’accessibilité (BFS/DFS), et non d’un problème de minimisation — l’approche gloutonne ne s’applique pas. Utilisez un BFS avec un ensemble des positions visitées pour éviter les cycles. Complexité temporelle : 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)

Jeu de sauts VII : accessibilité avec une portée

Jeu de sauts VII (LeetCode 1871) : pouvez-vous parcourir une chaîne binaire en sautant de l’indice 0 au dernier indice, sachant que depuis la position i, vous pouvez sauter vers n’importe quel ‘0’ dans [i+minJump, i+maxJump] ? Utilisez une somme sur fenêtre glissante appliquée au tableau des positions accessibles. Maintenez une somme préfixe des positions accessibles ; une position j est accessible s’il existe une position accessible dans [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

Comparaison des solutions gloutonne et BFS

Jeu de sauts II possède deux approches équivalentes en O(n) : l’extension gloutonne de portée et le parcours BFS niveau par niveau. L’approche gloutonne utilise O(1) espace, sans file, tandis que BFS utilise O(n) pour l’ensemble des positions visitées. En entretien, l’approche gloutonne est privilégiée pour son efficacité spatiale. Cependant, BFS est plus facile à dériver en premier — si vous avez du mal à trouver la solution gloutonne, codez d’abord BFS pour obtenir une solution fonctionnelle, puis optimisez-la. Les deux approches calculent correctement le nombre minimal de sauts.

# 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

Résumé de la complexité des jeux de sauts

Résumé de la complexité des variantes de Jeu de sauts : Jeu I (accessibilité) : O(n) en temps, O(1) en espace. Jeu II (sauts minimaux avec approche gloutonne) : O(n) en temps, O(1) en espace. Jeu II (BFS) : O(n) en temps, O(n) en espace. Jeu II (DP) : O(n × max_jump) en temps, O(n) en espace. Jeu III (BFS/DFS) : O(n) en temps, O(n) en espace pour les positions visitées. Jeu VII (fenêtre glissante) : O(n) en temps, O(n) en espace. Présentez toujours en entretien la solution gloutonne O(n) O(1) pour Jeu de sauts I et 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')

Vérification rapide

Évaluez votre compréhension des concepts de Structures de données et algorithmes — Préparation aux entretiens de programmation présentés dans cette leçon.

Récapitulatif de la leçon

Dans cette leçon, vous avez appris que : Jeu de sauts I utilise le suivi glouton de max_reach pour déterminer l’accessibilité en O(n) en temps et O(1) en espace, Jeu de sauts II utilise l’extension de portée avec curr_end et farthest pour compter le nombre minimal de sauts en O(n) et O(1), et l’extension gloutonne de portée équivaut à un BFS niveau par niveau sans le coût supplémentaire de la file. Nous allons maintenant appliquer le raisonnement glouton au délai de refroidissement de l’ordonnanceur de tâches et aux problèmes de faisabilité circulaire de la station-service.

Questions Fréquemment Posées

La leçon « Jeu des sauts I et II » est-elle gratuite ?

Oui — le texte complet de « Jeu des sauts I et II » est gratuit à lire ici sur le web. Pour la pratiquer de manière interactive (un éditeur de code intégré et un tuteur IA 24/7) et déverrouiller le reste du cours DSA Interview Prep, passe à CoddyKit PRO. Le cours DSA Interview Prep comprend 4 leçons au total.

Qu'est-ce que j'apprendrai dans « Jeu des sauts I et II » ?

Déterminez l’accessibilité et le nombre minimal de sauts à l’aide d’une approche gloutonne d’élargissement de plage, sans recourir à DP. Tu pratiques DSA Interview Prep avec du code pratique que tu exécutes directement dans le navigateur, et un tuteur IA 24/7 répond à tes questions au fur et à mesure que tu avances dans la leçon.

Dois-je avoir de l'expérience pour commencer DSA Interview Prep ?

Aucune expérience préalable n'est requise. DSA Interview Prep sur CoddyKit est structuré pour les débutants jusqu'aux apprenants avancés, donc tu peux commencer ici ou depuis le début et avancer à ton rythme. Ceci est la leçon 3 sur 4.

Combien de temps prend la leçon « Jeu des sauts I et II » ?

La plupart des leçons CoddyKit prennent environ 5–10 minutes. Chacune est courte et interactive, tu progresses régulièrement et tu repiques exactement où tu t'es arrêté sur le web et l'app.

Peux-tu écrire et exécuter du code dans cette leçon DSA Interview Prep ?

Oui. Chaque leçon DSA Interview Prep inclut un éditeur de code intégré, tu écris et exécutes du vrai code directement dans ton navigateur et tu reçois des retours IA instantanés — aucune configuration locale requise.

Toutes les leçons de ce cours

  1. Glouton ou DP : quand utiliser chaque approche
  2. Planification et fusion d’intervalles
  3. Jeu des sauts I et II
  4. Planificateur de tâches et station-service
← Retour à DSA Interview Prep