La espada se refiere a oferta100: la suma de los caminos más pequeños en el triángulo.

Pregunta:
dado un triángulo, encuentre la suma mínima de la ruta de arriba hacia abajo.
Cada paso solo puede moverse a nodos adyacentes en la siguiente fila. Los nodos adyacentes aquí se refieren a dos nodos cuyos subíndices son los mismos que los subíndices de los nodos en la capa anterior o iguales a los subíndices de los nodos en la capa anterior + 1. Es decir, si está en el índice i de la línea actual, el siguiente paso puede pasar al índice i o i + 1 de la siguiente línea.
Ejemplo 1:
Entrada: triángulo = [[2],[3,4],[6,5,7],[4,1,8,3]]
Salida: 11
Explicación: Como se muestra en el siguiente diagrama:
2
3 4
6 5 7
4 1 8 3
La suma mínima de la ruta descendente es 11 (es decir, 2 + 3 + 5 + 1 = 11).
Ejemplo 2:
Entrada: triángulo = [[-10]]
Salida: -10
Análisis:
Determine la ecuación de transición de estado , que se puede representar mediante f(i,j) comenzando desde la parte superior del triángulo y alcanzando los números de fila y columna i y j respectivamente (El valor mínimo de la suma de los números de ruta), mientras que T[i][j] representa el número de la fila del triángulo y los números de columna i y j, respectivamente. Si el triángulo contiene n filas de números, entonces el valor mínimo de f(n-1,j) es la solución óptima para todo el problema.

  • Si j es igual a 0, es decir, al primer número de una fila, ya que cada paso del camino va al número directamente debajo o abajo a la derecha, y no hay ningún número en la parte superior izquierda de la posición actual en esta vez, entonces el paso anterior debe provenir de él El número directamente arriba, por lo que f(i,0) es igual a la suma de f(i-1,0) y T[i][0].
  • Si i es igual a j, es decir, el último número de la fila actual, no hay ningún número directamente encima de él, y el paso anterior solo puede provenir del número en la parte superior izquierda, entonces f(i,j) es igual a f(i-1, La suma de j-1) y T[i][j].
  • Si el número de fila actual y el número de columna i y j están ubicados en el medio de una fila, entonces el paso anterior puede provenir del número directamente arriba o del número arriba a la izquierda, por lo que f(i,j) es igual a f El mínimo de (i-1,j) y f(i-1,j-1) más T[i][j].
    El primer método crea un arreglo bidimensional n*n dp Cuando solo se usa la parte inferior izquierda del arreglo, primero use una ecuación de transición de estado de bucle doble para calcular el valor de f(i, j) y guárdelo en dp[ i][j], y luego use un ciclo for para encontrar el valor mínimo de la última fila de la matriz bidimensional dp como la solución óptima para todo el problema. Dado que cada número en la parte inferior izquierda de la matriz bidimensional dp debe calcularse una vez, la complejidad del tiempo es O (n ^ 2). Suponiendo que el triángulo de entrada se implemente con una ArrayList, la complejidad temporal de llamar a la función get cada vez es O(1).
    Para optimizar la eficiencia del espacio, solo se requiere una matriz unidimensional dp. Si puede guardar f(i,j), f(i-1,j) en dp[j], entonces una matriz unidimensional puede guardar los datos requeridos.
    Si se calcula de izquierda a derecha, como se muestra en la figura: Luego de
    inserte la descripción de la imagen aquí
    calcular f(i,j), se reemplaza el primer elemento del arreglo dp. f(i,j-1) puede ser necesario al calcular f(i,j+1), pero f(i,j-1) es el primer elemento de la matriz dp original, pero se reemplazó, por lo que no se puede calcular de De izquierda a derecha, pero podemos calcular de derecha a izquierda. Si calculamos de derecha a izquierda, primero calculamos f(i, j), lo que requiere f(i-1, j-1), f(i- 1, j). Luego, para calcular f(i, j-1), necesitas usar f(i-1, j-1), f(i-1, j-2). Calcula f(i, j de derecha a izquierda) ), guardar el valor de f(i,j) en dp[j] y reemplazar f(i-1,j) no traerá ningún problema, por lo que el valor de f(i-1,j) ya no será más tarde necesario.
    Código:
import java.util.List;

public class MinimumTotal {
    
    
//
    public int minimumTotal1(List<List<Integer>> triangle) {
    
    
//        行数
        int size = triangle.size();
        int[][] dp = new int[size][size];
        for (int i = 0; i < size; i++) {
    
    
            for (int j = 0; j <= i; j++) {
    
    
                dp[i][j] = triangle.get(i).get(j);
//                如果得到的第一列下标为0,说明它的上一行元素下标也是0,因为下一行下标数字一定大于等于上一行下标数字
                if (i>0 && j==0){
    
    
                    dp[i][j] +=dp[i-1][j];
                }else if (i>0 && i==j){
    
    
//                    如果得到的行列数下标都相等,它的上一行元素一定也是对角线的元素,因为它上一行下标和它相等的不存在,只能找上一行
//                    同等下标左边那一个
                    dp[i][j] +=dp[i-1][j-1];
                }else if (i>0){
    
    
                    dp[i][j] +=Math.min(dp[i-1][j-1],dp[i-1][j]);
                }
            }
        }
        int min = Integer.MAX_VALUE;
//        找出二维数组dp最后一行的最小值作为整个问题的最优解
        for (int num:dp[size-1]){
    
    
            min = Math.min(min,num);
        }
        return min;
    }
    public int minimumTotal2(List<List<Integer>> triangle){
    
    
        int[] dp = new int[triangle.size()];
        for(List<Integer> row:triangle){
    
    
            for (int j = row.size()-1; j >=0; j--) {
    
    
                if (j==0){
    
    
                    dp[j]+=row.get(j);
                }else if (j == row.size()-1){
    
    
                    dp[j] = dp[j-1] + row.get(j);
                }else {
    
    
                    dp[j] = Math.min(dp[j],dp[j-1])+row.get(j);
                }
            }
        }
        int min = Integer.MAX_VALUE;
//        找出二维数组dp最后一行的最小值作为整个问题的最优解
        for (int num:dp){
    
    
            min = Math.min(min,num);
        }
        return min;
    }
}

inserte la descripción de la imagen aquí
inserte la descripción de la imagen aquí

Supongo que te gusta

Origin blog.csdn.net/Jiaodaqiaobiluo/article/details/123226966
Recomendado
Clasificación