leetcode動態規劃--基礎題

跳躍遊戲

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

數組中的每一個元素表明你在該位置能夠跳躍的最大長度。函數

判斷你是否可以到達最後一個位置。code

思路

根據題目意思,最大跳躍距離,說明能夠跳0--nums[i]的距離
能夠把跳躍當作走nums[i]步,若是能走到下一位置則能夠加油獲取更多的步數(nums[j]步),可是不能累加
那麼只需掃一遍nums數組,更新剩餘能跳的距離(注意不能累加,只能取最大!)
到終點以前判斷是否有剩餘步驟便可blog

代碼

class Solution {
public:
    bool canJump(vector<int>& nums) {
        if(nums.size()==0)return false;
        int cur=nums[0];
        for(int i=1;i<nums.size();++i){
            if(cur<=0){
                return false;
            }
            cur--;
            cur=std::max(cur,nums[i]);
        }
        return true;
    }
};

不一樣路徑

一個機器人位於一個 m x n 網格的左上角 (起始點在下圖中標記爲「Start」 )。遊戲

機器人每次只能向下或者向右移動一步。機器人試圖達到網格的右下角(在下圖中標記爲「Finish」)。圖片

問總共有多少條不一樣的路徑?
圖片leetcode

思路

當前位置能夠來自上方或者左邊
令dp[i][j]表示第i行第j列的路徑數,則dp[i][j]=dp[i-1][j]+dp[i][j-1];
注意邊界便可get

代碼

class Solution {
public:
    int uniquePaths(int m, int n) {
        int path[m+1][n+1];
        memset(path,0,sizeof(path));
        path[0][1]=1;
        for(int i=1;i<=m;++i){
            for(int j=1;j<=n;++j){
                path[i][j]=path[i-1][j]+path[i][j-1];
            }
        }
        return path[m][n];
    }
};

零錢兌換

給定不一樣面額的硬幣 coins 和一個總金額 amount。編寫一個函數來計算能夠湊成總金額所需的最少的硬幣個數。若是沒有任何一種硬幣組合能組成總金額,返回 -1。io

思路

一開始想法是搜索,可是超時了(大概是我太菜了吧)
接着想到每一中硬幣選的個數最多爲amount / coins[i]
接着就是將其轉化爲0/1揹包問題求解
dp[i][j]表示前i個硬幣組成金額 j 的最少硬幣個數
dp[i][j] = min(dp[i-1][j-k*coins[i]) , 0<=k<=j/coins[i];class

代碼

代碼寫的太醜了

class Solution {
public:
    int coinChange(vector<int>& coins, int amount) {
        if(coins.size()==0)return -1;
        int cn=coins.size();
        int dp[cn+1][amount+1];
        for(int i=0;i<=cn;++i){
            for(int j=0;j<=amount;++j){
                dp[i][j]=-1;
            }
        }
        for(int i=0;i<=cn;++i){
            dp[i][0]=0;
        }
        // 第一個硬幣
        for(int i=1;i<=amount;++i){
            if(i%coins[0]==0){
                dp[0][i]=i/coins[0];
            }
        }
        for(int i=1;i<cn;++i){
            for(int j=0;j<=amount;++j){
                // 第i枚硬幣選擇k個
                for(int k=0;k*coins[i]<=j;++k){
                    if(dp[i-1][j-k*coins[i]]!=-1){
                        if(dp[i][j]==-1){
                            dp[i][j]=dp[i-1][j-k*coins[i]]+k;
                        }else{
                            dp[i][j]=min(dp[i][j],dp[i-1][j-k*coins[i]]+k);
                        }
                    }
                }
            }
        }
        
        return dp[cn-1][amount];
    }
};

Longest Increasing Subsequence

最長上升子串

思路

令dp[i]表示以nums[i]做爲結尾的最大上升子序列的最大長度
內層循環在前面找比nums[i]小的元素,能夠將nums[i]接到j後面使得LIS長度加1
dp[i] = max(dp[j]+1) ,nums[i]>nums[j]&&0<=j<i;
注意最後返回dp的最大值

代碼

class Solution {
public:
    int lengthOfLIS(vector<int>& nums) {
        if(nums.size()==0||nums.size()==1)return nums.size();
        int dp[nums.size()];
        for(int i=0;i<nums.size();++i){
            dp[i]=1;
        }
        int ans=-1;
        for(int i=0;i<nums.size();++i){
            for(int j=0;j<i;++j){
                if(nums[i]>nums[j]){
                    dp[i]=std::max(dp[i],dp[j]+1);
                }
            }
            ans=std::max(ans,dp[i]);
        }
        return ans;
    }
};
相關文章
相關標籤/搜索