55 juegos de saltos (recursivos, programación dinámica, codiciosos)

1. Descripción del problema:

Dada una matriz de enteros no negativos, inicialmente se encuentra en la primera posición de la matriz.

Cada elemento de la matriz representa la longitud máxima que puede saltar en esa posición.

Determine si puede alcanzar la última posición.

Ejemplo 1:

Entrada: [2,3,1,1,4]
Salida: verdadero
Explicación: Podemos saltar 1 paso desde la posición 0 a la posición 1, luego saltar 3 pasos desde la posición 1 a la última posición.
Ejemplo 2

Entrada: [3,2,1,0,4]
Salida: falso
Explicación: Pase lo que pase , siempre alcanzará el índice 3. Pero la longitud máxima de salto de esta posición es 0, por lo que nunca puede llegar a la última posición.

Fuente: LeetCode (LeetCode)
Enlace: https://leetcode-cn.com/problems/jump-game

2. Análisis de pensamiento:

① También he escrito un blog sobre este tema antes, usando bfs width-first search para resolverlo, y descubrí que casi nadie usa esta idea en el collar, incluida la solución oficial no usa bfs para resolver el código Las soluciones más utilizadas son el retroceso recursivo, la programación dinámica y la codicia. Entre estas soluciones oficiales, son muy dignas de nuestro estudio y muy valiosas. Es muy valioso para nosotros resolver tales problemas. Es útil y necesita ser entendido. Lo siguiente es mi propio entendimiento del método dado por la solución oficial

First El primer método es usar la recursión, que es relativamente fácil de pensar, porque es obvio que el título nos dice que cada posición puede saltar en la mayoría de los nums [i] pasos a la derecha, por lo que comenzamos desde el punto de partida e intentamos saltar desde la posición actual a Para otras posiciones, el número de intentos es como máximo nums [i], por lo que puede usar la recursión para resolver, pruebe si cada posición puede saltar a la última posición, si descubre que puede alcanzar la última posición durante la solución intermedia, luego directamente en el proceso intermedio Simplemente regrese en el medio, que también es diferente de la recurrencia del valor de retorno anterior. Anteriormente, debe intentar resolver todas las respuestas antes de que finalmente pueda completar este proceso recursivo. Aquí puede encontrar que hay uno en el medio que puede regresar tan directamente, porque la solución El problema es diferente, todos los métodos de tratamiento serán diferentes, pero generalmente iguales

③ El segundo método utiliza la recursividad basada en la memoria para resolver, principalmente con la ayuda de intentos recursivos, pero aquí se utiliza una matriz para registrar los resultados de la solución intermedia, que es esencialmente lo mismo que nuestra recursividad previa basada en la memoria. Es lo mismo. Si encuentra que se ha resuelto antes, vuelva directamente al valor resuelto previamente. Utilice los tres métodos de marcado de tipo enum para indicar si la posición actual puede saltar a la última coordenada. Todo el proceso es relativamente fácil de entender. Oficial Solución recursiva de arriba hacia abajo

Third El tercer método es similar al segundo método. Aquí, la recursión se usa de abajo hacia arriba, comenzando desde la penúltima posición para ver si puede alcanzar la última posición. Si puede marcar esta posición como una buena posición, Si no es posible, marque esta posición como mala, y luego continúe intentando llegar a la posición anterior para ver si la posición actual puede alcanzar la posición correcta previamente marcada, continúe intentando de esta manera y finalmente vea si la primera posición Es una buena posición, porque si la primera posición es una buena posición, definitivamente puedes alcanzar la buena posición marcada antes cuando vas a la derecha, así que finalmente juzga la posición inicial.

Fourth El cuarto método es una estrategia codiciosa, que es más fácil de entender pero difícil de encontrar. Pruébelo desde la penúltima posición a la derecha. Vea si la posición actual más la distancia máxima que se puede saltar es mayor o igual que la última posición Ser capaz de alcanzar indica que la posición actual es una buena posición. En este momento, la posición izquierda se actualiza. El proceso de intentar avanzar hasta la primera posición. De hecho, toda la idea es relativamente fácil de entender.

3. El código oficial es el siguiente:

Código recursivo:

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);
    }
}

Recurrencia de memoria:

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);
    }
}

Planificación dinámica:

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;
    }
}

Codicioso:

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;
    }
}

 

569 artículos originales publicados · Me gusta 153 · Visitas 590,000+

Supongo que te gusta

Origin blog.csdn.net/qq_39445165/article/details/105367829
Recomendado
Clasificación