55 jeux de saut (récursif, programmation dynamique, gourmand)

1. Description du problème:

Étant donné un tableau d'entiers non négatifs, vous êtes initialement dans la première position du tableau.

Chaque élément du tableau représente la longueur maximale que vous pouvez sauter à cette position.

Déterminez si vous pouvez atteindre la dernière position.

Exemple 1:

Entrée: [2,3,1,1,4]
Sortie: vrai
Explication: Nous pouvons sauter 1 pas de la position 0 à la position 1, puis sauter 3 pas de la position 1 à la dernière position.
Exemple 2:

Entrée: [3,2,1,0,4]
Sortie: false
Explication: Quoi qu'il en soit, vous atteindrez toujours l'index 3. Mais la longueur de saut maximale de cette position est 0, vous ne pouvez donc jamais atteindre la dernière position.

Source: LeetCode (LeetCode)
Lien: https://leetcode-cn.com/problems/jump-game

2. Analyse de la pensée:

① J'ai également écrit un blog sur ce sujet auparavant, en utilisant la recherche en premier sur la largeur de bfs pour le résoudre, et j'ai constaté que presque personne n'utilise cette idée dans le collier, y compris la solution officielle n'utilise pas bfs pour résoudre le code Les solutions les plus couramment utilisées sont le backstacking récursif, la programmation dynamique et gourmande. Parmi ces solutions officielles, elles sont très dignes de notre étude et très précieuses. Il est très précieux pour nous de résoudre de tels problèmes. Il est utile et doit être compris. Ce qui suit est ma propre compréhension de la méthode donnée par la solution officielle

② La première méthode consiste à utiliser la récursivité, ce qui est relativement facile à penser, car il est évident que le titre nous dit que chaque position peut sauter au plus nums [i] pas vers la droite, donc nous partons du point de départ et essayons de sauter de la position actuelle à Pour les autres positions, le nombre de tentatives est au plus nums [i], vous pouvez donc utiliser la récursivité pour résoudre, essayez si chaque position peut sauter à la dernière position, si vous trouvez que vous pouvez atteindre la dernière position pendant la solution intermédiaire, puis directement dans le processus intermédiaire Il suffit de revenir au milieu, ce qui est également différent de la récursivité de la valeur de retour précédente. Auparavant, vous devez essayer de résoudre toutes les réponses avant de pouvoir enfin terminer ce processus récursif. Ici, vous pouvez trouver qu'il y en a une au milieu qui peut retourner si directement, car la solution Le problème est différent, toutes les méthodes de traitement seront différentes, mais généralement les mêmes

③ La deuxième méthode utilise une récursion basée sur la mémoire pour résoudre, principalement à l'aide de tentatives récursives, mais ici un tableau est utilisé pour enregistrer les résultats de la solution intermédiaire, qui est essentiellement le même que notre précédente récursion basée sur la mémoire. Il en est de même. Si vous trouvez qu'il a été résolu auparavant, revenez directement à la valeur précédemment résolue. Utilisez les trois méthodes de marquage de type enum pour indiquer si la position actuelle peut atteindre la dernière coordonnée. L'ensemble du processus est relativement facile à comprendre. Solution récursive descendante

④ La troisième méthode est similaire à la deuxième méthode. Ici, la récursivité est utilisée de bas en haut, à partir de l'avant-dernière position pour voir si vous pouvez atteindre la dernière position. Si vous pouvez marquer cette position comme une bonne position, Si ce n'est pas possible, marquez cette position comme une mauvaise position, puis continuez à essayer jusqu'à la position précédente pour voir si la position actuelle peut atteindre la bonne position précédemment marquée, continuez à essayer de cette façon et enfin voyez si la première position C'est une bonne position, car si la première position est une bonne position, vous pouvez certainement atteindre la bonne position marquée avant lorsque vous allez à droite, alors jugez enfin la position initiale.

Fourth La quatrième méthode est une stratégie gourmande, plus facile à comprendre mais plus difficile à trouver. Essayez-la depuis l'avant-dernière position à droite, et voyez si la position actuelle plus la distance maximale pouvant être franchie est supérieure ou égale à la dernière position. Être en mesure d'atteindre indique que la position actuelle est une bonne position. À l'heure actuelle, la position de gauche est mise à jour. Le processus consistant à essayer d'avancer jusqu'à la première position. En fait, l'idée globale est relativement facile à comprendre.

3. Le code officiel est le suivant:

Code récursif:

public class Solution {
    public boolean canJumpFromPosition(int position, int[] nums) {
        if (position == nums.length - 1) {
            return true;
        }
        int furthestJump = Math.min(position + nums[position], nums.length - 1);
        for (int nextPosition = position + 1; nextPosition <= furthestJump; nextPosition++) {
            if (canJumpFromPosition(nextPosition, nums)) {
                return true;
            }
        }
        return false;
    }

    public boolean canJump(int[] nums) {
        return canJumpFromPosition(0, nums);
    }
}

Récursivité de la mémoire:

enum Index {
    GOOD, BAD, UNKNOWN
}

public class Solution {
    Index[] memo;
    public boolean canJumpFromPosition(int position, int[] nums) {
        if (memo[position] != Index.UNKNOWN) {
            return memo[position] == Index.GOOD ? true : false;
        }

        int furthestJump = Math.min(position + nums[position], nums.length - 1);
        for (int nextPosition = position + 1; nextPosition <= furthestJump; nextPosition++) {
            if (canJumpFromPosition(nextPosition, nums)) {
                memo[position] = Index.GOOD;
                return true;
            }
        }
        memo[position] = Index.BAD;
        return false;
    }

    public boolean canJump(int[] nums) {
        memo = new Index[nums.length];
        for (int i = 0; i < memo.length; i++) {
            memo[i] = Index.UNKNOWN;
        }
        memo[memo.length - 1] = Index.GOOD;
        return canJumpFromPosition(0, nums);
    }
}

Planification dynamique:

enum Index {
    GOOD, BAD, UNKNOWN
}

public class Solution {
    public boolean canJump(int[] nums) {
        Index[] memo = new Index[nums.length];
        for (int i = 0; i < memo.length; i++) {
            memo[i] = Index.UNKNOWN;
        }
        memo[memo.length - 1] = Index.GOOD;
        for (int i = nums.length - 2; i >= 0; i--) {
            int furthestJump = Math.min(i + nums[i], nums.length - 1);
            for (int j = i + 1; j <= furthestJump; j++) {
                if (memo[j] == Index.GOOD) {
                    memo[i] = Index.GOOD;
                    break;
                }
            }
        }

        return memo[0] == Index.GOOD;
    }
}

Gourmand:

public class Solution {
    public boolean canJump(int[] nums) {
        int lastPos = nums.length - 1;
        for (int i = nums.length - 1; i >= 0; i--) {
            if (i + nums[i] >= lastPos) {
                lastPos = i;
            }
        }
        return lastPos == 0;
    }
}

 

Publié 569 articles originaux · loué 153 · 590 000 vues

Je suppose que tu aimes

Origine blog.csdn.net/qq_39445165/article/details/105367829
conseillé
Classement