算法學習 —— 動態規劃練習(二)

1、不一樣路徑(LeetCode-62)

1.1 題目介紹

62. 不一樣路徑java

1.2 解題思路

計數型動態規劃數組

最後一步ide

最右下角的座標假設爲(m,n),則假設走到(m,n)全部可能的路徑爲f[m][n]spa

子問題code

走到(m,n)的前一步有兩種可能一種是(m-1,n),一種是(m,n-1)視頻

狀態轉移方程blog

f[m][n] = f[m-1][n] + f[m][n-1]索引

初始化和邊界 由於根據題意,只能向右走,或向下走。從(0,0)到位於(0,n)或(m,0)這點位置,都只有一種走法。 i = 0 或 j = 0 ,則f[i][j] = 0遊戲

1.3 解題代碼

class Solution {
    public int uniquePaths(int m, int n) {
        int[][] f = new int[m][n];
        //最後一步
        //f[m-1][n-1] = f[m-1][n-2] + f[m-2][n-1]
        //初始條件
        //f[0][j] = 1  f[i][0] = 1 
        int i,j;
        for(i=0;i<m;i++){
            for(j=0;j<n;j++){
                if(i==0||j==0){
                    f[i][j] = 1;
                }else{
                    f[i][j] = f[i-1][j] + f[i][j-1];
                }
                
            }
        }
        return f[m-1][n-1];
    }
}

2、跳躍遊戲(LeetCode-55)

2.1 題目介紹

55. 跳躍遊戲leetcode

給定一個非負整數數組,你最初位於數組的第一個位置。

數組中的每一個元素表明你在該位置能夠跳躍的最大長度。 判斷你是否可以到達最後一個位置。

示例 1: 輸入: [2,3,1,1,4] 輸出: true 解釋: 從位置 0 到 1 跳 1 步, 而後跳 3 步到達最後一個位置。

示例 2: 輸入: [3,2,1,0,4] 輸出: false 解釋: 不管怎樣,你總會到達索引爲 3 的位置。但該位置的最大跳躍長度是 0 , 因此你永遠不可能到達最後一個位置。

2.2 解題思路

存在型動態規劃

最後一步 肯定狀態,最後一步,是f[n]可否走到n的位置

子問題 可否走到f[n],在n以前,若是有i+a[i] >= n 的話,而且f[i]能夠到達,則f[n]也能夠到達

狀態轉移方程

f[x] = f[i] & (i + a[i] >=x)

0 < i < x

初始化 f[0] = 0

2.3 解題代碼

class Solution {
    public boolean canJump(int[] nums) {
        int n = nums.length;
        boolean[] f = new boolean[n];
        int i,j;
        f[0] = true;
        for(i=1;i<n;i++){
            f[i] = false;
            for(j=0;j<i;j++){
                if(f[j] && j+nums[j] >= i){
                    f[i] = true;
                    break;
                }
            }
        }
        return f[n-1];
        
    }
}

3、1155. 擲骰子的N種方法(LeetCode-1155)

3.1 題目介紹

這裏有 d 個同樣的骰子,每一個骰子上都有 f 個面,分別標號爲 1, 2, ..., f。

咱們約定:擲骰子的獲得總點數爲各骰子面朝上的數字的總和。

若是須要擲出的總點數爲 target,請你計算出有多少種不一樣的組合狀況(全部的組合狀況總共有 f^d 種),模 10^9 + 7 後返回。

3.2 解題思路

該題屬於計數型動態規劃

根據題意,設dp[d][target]是用擲d個骰子,骰子的面數f,獲得和爲target的方法數。

假設d=3,f=5,target = 19

(1)最後一步:

d[3][19] = d[2][19-1] +  d[2][19-2] +  d[2][19-3] +  d[2][19-4] +  d[2][19-5]

因爲 d[3][19]初始化爲0,因此上面的公式能夠簡化爲

for (i = 1;i<5;i++)
    d[3][19] += d[3-1][19 - i]

(2)初始條件

當只有一個骰子時,有f個面,咱們知道得到x(1<=x<=f)的方法均爲1種。

因此

for(i=1;i<f;i++)
    dp[1][i] = 1

(3)狀態轉移方程

for(i = 2;i<=d;i++)
    for(j = 1;j<=target;j++)
        for (k = 1;k<=f;k++)
            // j>=k
            dp[i][j] += d[i-1][j-k]

(4)邊界

循環結束,i = d,j = target,即到達邊界點,也就求出解。

3.3 解題代碼

public int numRollsToTarget(int d, int f, int target) {

        int[][] dp = new int[31][1001];
        //初始化條件,只有1個骰子的時候,1-f的方法均只有1種
        for (int i = 1; i <= f; i++) {
            dp[1][i] = 1;
        }
        //骰子數
        for (int i = 2; i <= d; i++) {
            //要湊出的面值
            for (int j = 1; j <= target; j++) {
                //骰子面值
                for (int k = 1; k <= f; k++) {
                    if (j >= k) {
                        dp[i][j] += dp[i - 1][j - k];
                        dp[i][j] %= 1000000007;
                    }
                }
            }
        }
        return dp[d][target];

    }

4、單字符重複子串的最大長度(LeetCode-1156)

佔坑,待AC。

若是字符串中的全部字符都相同,那麼這個字符串是單字符重複的字符串。

給你一個字符串 text,你只能交換其中兩個字符一次或者什麼都不作,而後獲得一些單字符重複的子串。返回其中最長的子串的長度。

輸入輸出

輸入:text = "ababa"
輸出:3

輸入:text = "aaabaaa"
輸出:6


輸入:text = "aaabbaaa"
輸出:4


輸入:text = "aaaaa"
輸出:5


輸入:text = "abcdef"
輸出:1

參考視頻

動態規劃入門 Introduction to Dynamic Programming

相關文章
相關標籤/搜索