アルゴリズムレビュー:動的計画を達成するために、再帰的に階段の問題フィボナッチ数からの反射、

問題は、鉛:
leetcodeのNo.70

そのような練習を開始しない場合:

考えてみ
ない仕事を、次の1暴力を解決することができ考える
問題はもっと考えられ、一般的にまとめた数学的帰納法の基本的な状況を見て周りの比較そして複雑であるため、2を
サブ問題の最新の反復を見つけること3.検索ロジック、それは、部分的に問題を発見し、ある繰り返し
-再帰または動的プログラミングを使用することを検討してください

再帰

1.最も一般的な愚か再帰O(2 ^ n)との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.プラス再帰バッファのアレイ(先行の木の子孫は、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.キャッシュされた再帰的なハッシュマップを使用して2plus方法

//这个方法也是可以的!! 但是只是适用于在输入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.方法4:便利な動的プログラミング(ボトムアップ動的プログラミング)又は(サブ問題解決)当たりの結果の配列を作成する親で記録計画問題
の動的計画法のメモが存在するという事実に(からトップダウン)

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;

計画記録された結果(子供の問題の解決策)を必要としない各配列を必要としない(また、フィボナッチとしても知られる)動的プログラミングプラス
各サブ問題があるためすることができ、最後の三つの値の間にのみ存在しますその解決策は、第3番目の番号へのカウントダウンは確かに最後の数の子供の問題の解決策になることができますので、彼は常に変化している状況の親の動的変換の問題の解決策であります

//复习前一天:
// 方法五: 动态规划 但不使用循环 无需记录过程中的数 但是只需要记住最后的三个数即可 因为过程中每次子问题的解是动态变换的  也就是说作为解父问题的条件他是不断变换的 那么到了倒数的第二个第三个数 肯定是可以成为最后一个属的子问题的解 
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; 
         }          
    }

違い「再帰」と持っている「反復」とは何ですか?

公開された81元の記事 ウォン称賛19 ビュー3603

おすすめ

転載: blog.csdn.net/c22cxz/article/details/105030128