Algoritmo revisão: uma reflexão a partir do problema de números de Fibonacci escadas de forma recursiva, para alcançar programação dinâmica

Problemas levar:
No.70 leetcode

Se ele não iniciar quando tal prática:

Considere
não trabalho, então considerar a 1. Violência seguinte pode resolver
2. Porque o problema é mais complicado então comparar ao redor para olhar para a situação básica de indução matemática resumida em geral considerada
lógica 3. Localizar para encontrar o mais recente iteração do sub-problemas , isto é, para encontrar o problema, em parte, repetiu
- considerar o uso de recursão ou programação dinâmica

recursão

1. O burro O recursiva mais comum (2 ^ n) e podem conduzir a StackOverflow

// 方法一:直接递归  
// 但是这道题有点和斐波那契数列稍稍不符合的地方是 f0=0 而数列中f0=1;
class Solution {
    public int climbStairs(int n) {
          
         if(n == 0) { //不同处 f0=0,它有点点不符合斐波那契数列的思想 而数列中f0=1;
             return 0;
         }   
         if(n == 1) {
            return 1;
         }
         if(n == 2) {
          	return 2;
         }
            return  climbStairs(n-2) + climbStairs(n-1); 
         }  
    }

2. além de uma matriz de tampão recursiva (antecessores árvores descendentes arrefecer LOL)

//这个方法是可以的!! 但是只是适用于在输入44之前的数
// 方法二:记忆化递归 有缓存的思想 创一个数组 每次把递归的结果记录下来 方便下一次递归使用
//每当函数再次被递归调用时,我们就直接从 memo 数组返回结果。
// 但是这道题有点和斐波那契数列稍稍不符合的地方是 f0=0 而数列中f0=1;
class Solution {
    public int climbStairs(int n) {
         int memo[] = new int[n + 1];//防止递归时 溢出
         if(n == 0) { //不同处 f0=0,它有点点不符合斐波那契数列的思想 而数列中f0=1;
             memo[0] = 0;
             return 0;
         }   
         if(n == 1) {
             memo[1] = 1;
             return 1;
         }
         if(n == 2) {
             memo[2] = 2;
             return 2;
         }
         //接下来 和普通递归不同处是 每次先找缓存里面找我需要的递归式 是否已经在上一步算出来并且缓存了
         if(memo[n] != 0) { //因为java数组默认全部填0  那么我这里如果判断n这个位置不是0 说明已经缓存过 
            return memo[n]; //那就返回即可
         } else { //说明之前没缓存 需要缓存 给后面用 (前人栽树后人乘凉LOL)
            int rst = climbStairs(n-2) + climbStairs(n-1); 
            memo[n] = rst;
            return rst; 
         }  
    }
}

3. O método 2plus usando hashmap recursiva em cache

//这个方法也是可以的!! 但是只是适用于在输入44之前的数
// 方法三:记忆化递归plus 有缓存的思想 创一个数组 每次把递归的结果记录下来 方便下一次递归使用
//每当函数再次被递归调用时,和前一种方法的存储不同,前一种我们是从 数组memo[] 返回结果。 而现在可以使用hashmap(好处是使用它内部的查询优化)
// 但是这道题有点和斐波那契数列稍稍不符合的地方是 f0=0 而数列中f0=1;
class Solution {
    public int climbStairs(int n) {
        //  int memo[] = new int[n + 1];//防止递归时 溢出 不用它了 用hashmap
      Map<Integer, Integer> memo = new HashMap<>();
         if(n == 0) { //不同处 f0=0,它有点点不符合斐波那契数列的思想 而数列中f0=1;
             memo.put(0,0);
             return 0;
         }   
         if(n == 1) {
             memo.put(1,1);
             return 1;
         }
         if(n == 2) {
             memo.put(2,2);
             return 2;
         }
         //接下来 和普通递归不同处是 每次先找缓存里面找我需要的递归式 是否已经在上一步算出来并且缓存了
         if(null != memo.get(n)) { //能取到值 说明已经缓存过 
            return memo.get(n); //那就返回即可
         } else { //说明之前没缓存 需要缓存 给后面用 (前人栽树后人乘凉LOL)
            int rst = climbStairs(n-2) + climbStairs(n-1); 
            memo.put(n,rst);
            return rst; 
         }  
    }
}

4. Método de quatro: programação dinâmica (de baixo para cima de programação dinâmico) ou criar uma matriz dos resultados por (soluções de sub-problema) gravado problema de programação com um progenitor convenientemente
na verdade não existe um método de exposição de programação dinâmica (a partir de de cima para baixo)

class Solution {
    public int climbStairs(int n) {
        // int dp[] = new int[n+1];//当n取1 这就会报错 所以可以再开大点
        int dp[] = new int[n+2]; 
        if (n == 0) {
            return 0;
        }
        // if (n == 1) {
        //     return 1;
        // }
        // if (n == 2) {
        //     return 2;
        // } //实际可以用下一句代替 因为程序最好单一出口 或者少出口 但是写上的话 易读性更好
        dp[1] = 1;
        dp[2] = 2;
        for(int i = 3; i <= n; i++) {
            dp[i] = dp[i-2] + dp[i-1];
        }
        return dp[n];
    }
}

// / 方法四:动态规划 还是 创一个数组 每次把规划的结果(子问题的解)记录下来 方便下一次父问题使用
 // 但是这道题有点和斐波那契数列稍稍不符合的地方是 f0=0 而数列中f0=1;

A programação dinâmica mais (também conhecido como Fibonacci) não requer cada matriz não requer os resultados (solução do problema da criança) gravados no planejamento de
cada sub-problemas só existem durante os últimos três valores pode ser porque que a solução é uma solução do problema da transformação dinâmica pai das condições ele está constantemente mudando tão a contagem regressiva para o segundo terceiro número certamente pode ser uma solução para o problema da criança durar um número de

//复习前一天:
// 方法五: 动态规划 但不使用循环 无需记录过程中的数 但是只需要记住最后的三个数即可 因为过程中每次子问题的解是动态变换的  也就是说作为解父问题的条件他是不断变换的 那么到了倒数的第二个第三个数 肯定是可以成为最后一个属的子问题的解 
class Solution {
    public int climbStairs(int n) {
        int rst = 0;
        int f1 = 1;
        int f2 = 2;
        if(n == 0) { //不同处 f0=0,它有点点不符合斐波那契数列的思想 而数列中f0=1;  
             return 0;
         }   
         if(n == 1) {
            return 1;
         }
         if(n == 2) {
          	return 2;
         }
         for(int i = 3; i <= n; i++) {
             rst = f2 + f1;
             f1 = f2;
             f2 = rst;
         }   
         return  rst; 
         }          
    }

Quais são as diferenças "recursão" e "iterativo" tem?

Publicado 81 artigos originais · ganhou elogios 19 · vista 3603

Acho que você gosta

Origin blog.csdn.net/c22cxz/article/details/105030128
Recomendado
Clasificación