動態規劃題集

題一:leetcode:1143(最長公共子序列)
(https://leetcode-cn.com/problems/longest-common-subsequence/)
題目描述:
給定兩個字符串 text1 和 text2,返回這兩個字符串的最長公共子序列。
一個字符串的 子序列 是指這樣一個新的字符串:它是由原字符串在不改變字符的相對順序的情況下刪除某些字符(也可以不刪除任何字符)后組成的新字符串。
例如,"ace" 是 "abcde" 的子序列,但 "aec" 不是 "abcde" 的子序列。兩個字符串的「公共子序列」是這兩個字符串所共同擁有的子序列。
若這兩個字符串沒有公共子序列,則返回 0。
代碼:

class Solution {
public:
    int longestCommonSubsequence(string text1, string text2) {
        int len1 = text1.length();
        int len2 = text2.length();
        if(len1 == 0 || len2 == 0)
            return 0;
        vector<vector<int>> data(len1+1, vector<int>(len2+1, 0));
        for(int i = 1; i <= len1; i++)
        {
            for(int j = 1; j <= len2; j++)
            {
                if(text1[i-1] == text2[j-1])
                {
                    data[i][j] = data[i-1][j-1]+1;
                }
                else
                {
                    data[i][j] = max(data[i-1][j], max(data[i][j-1], data[i-1][j-1])); 
                }
            }
        }
        return data[len1][len2];
    }
};

題二:leetcode:62(不同路徑)
(https://leetcode-cn.com/problems/unique-paths/submissions/)
題目描述:
一個機器人位于一個 m x n 網格的左上角 (起始點在下圖中標記為“Start” )。
機器人每次只能向下或者向右移動一步。機器人試圖達到網格的右下角(在下圖中標記為“Finish”)。
問總共有多少條不同的路徑?

class Solution {
public:
    int uniquePaths(int m, int n) {
        vector<vector<int>> data(m , vector<int>(n, 0));
        for(int i = 0; i < m; i++)
        {
            for(int j = 0; j < n; j++)
            {
                if(i == 0 || j == 0)
                {
                    data[i][j] = 1;
                }
                else
                {
                    data[i][j] = data[i-1][j] + data[i][j-1];   
                }
            }
        }
        return data[m-1][n-1];
    }
};
//data[i][j] 走到第ij點,有多少路徑
//data[i][j] = max(data[i-1][j], data[i][j-1])

題三:leetcode:63(不同路徑II)
(https://leetcode-cn.com/problems/unique-paths-ii/submissions/)
題目描述:
一個機器人位于一個 m x n 網格的左上角 (起始點在下圖中標記為“Start” )。
機器人每次只能向下或者向右移動一步。機器人試圖達到網格的右下角(在下圖中標記為“Finish”)。
現在考慮網格中有障礙物。那么從左上角到右下角將會有多少條不同的路徑?

class Solution {
public:
    int uniquePathsWithObstacles(vector<vector<int>>& obstacleGrid) {
        if(obstacleGrid.empty()) return 0;
        long r = obstacleGrid.size();
        long c = obstacleGrid[0].size();
        vector<vector<long>> data(r+1, vector<long>(c+1, 0));
        for(long i = 1; i <= r; i++)
        {
            for(long j = 1; j <= c; j++)
            {
                if(i == 1 && j == 1)
                {
                    data[i][j] = obstacleGrid[i-1][j-1] == 0 ? 1 : 0;
                }
                else
                {
                    data[i][j] = obstacleGrid[i-1][j-1] == 1 ? 0 : data[i-1][j]+data[i][j-1];
                }
            }
        }
        return static_cast<int>(data[r][c]);
    }
};

題四:leetcode:70(爬樓梯)
(https://leetcode-cn.com/problems/climbing-stairs/submissions/)
題目描述:
假設你正在爬樓梯。需要 n 階你才能到達樓頂。
每次你可以爬 1 或 2 個臺階。你有多少種不同的方法可以爬到樓頂呢?
注意:給定 n 是一個正整數。

class Solution {
public:
    int climbStairs(int n) {
        vector<int> data(n, 0);
        for(int i = 0; i < n; i++)
        {
            if(i == 0) data[i] = 1;
            else if(i == 1) data[i] = 2;
            else data[i] = data[i-1] + data[i-2];
        }
        return data[n-1];
    }
};

題五:leetcode:120(三角形最小路徑和)
(https://leetcode-cn.com/problems/triangle/)
題目描述:
給定一個三角形,找出自頂向下的最小路徑和。每一步只能移動到下一行中相鄰的結點上。

例如,給定三角形:
[
[2],
[3,4],
[6,5,7],
[4,1,8,3]
]
自頂向下的最小路徑和為 11(即,2 + 3 + 5 + 1 = 11)。
自頂向下:

class Solution {
public:
    int minimumTotal(vector<vector<int>>& triangle) {
        if(triangle.empty()) return 0;
        int r = triangle.size();
        int maxc = triangle[r-1].size();
        vector<vector<int>> data(r+2, vector<int>(maxc+2, 0));
        int minValue = INT_MAX;
        for(int i = 1; i <= r; i++)
        {
            for(int j = 1; j <= triangle[i-1].size(); j++)
            {
                if(i == 1) data[i][j] = triangle[i-1][j-1];
                else if(j == 1) data[i][j] = data[i-1][j] + triangle[i-1][j-1];
                else if(j == triangle[i-1].size()) data[i][j] = data[i-1][j-1]+ triangle[i-1][j-1];
                else data[i][j] =  min(data[i-1][j], data[i-1][j-1]) + triangle[i-1][j-1];
                if(i == r)
                {
                    minValue = minValue < data[i][j] ? minValue : data[i][j];
                }
            }
        }
        return minValue;
        
    }
};

題六:leetcode:53(最大子序和)
(https://leetcode-cn.com/problems/maximum-subarray/)
題目描述:
給定一個整數數組 nums ,找到一個具有最大和的連續子數組(子數組最少包含一個元素),返回其最大和。
示例:
輸入: [-2,1,-3,4,-1,2,1,-5,4],
輸出: 6
解釋: 連續子數組 [4,-1,2,1] 的和最大,為 6。
進階:
如果你已經實現復雜度為 O(n) 的解法,嘗試使用更為精妙的分治法求解。

class Solution {
public:
    int maxSubArray(vector<int>& nums) {
        if(nums.empty()) return 0;
        int len = nums.size();
        vector<int> data(len, 0);
        data[0] = nums[0];
        int maxVal = data[0];
        for(int i = 1; i < len; i++)
        {
            data[i] = data[i-1] > 0 ? data[i-1]+nums[i] : nums[i];
            maxVal = maxVal > data[i] ? maxVal : data[i];
        } 
        return maxVal;
    }
};

題七:leetcode:152(乘積最大子序列)
(https://leetcode-cn.com/problems/maximum-product-subarray/)
題目描述:
給定一個整數數組 nums ,找出一個序列中乘積最大的連續子序列(該序列至少包含一個數)。
示例 1:
輸入: [2,3,-2,4]
輸出: 6
解釋: 子數組 [2,3] 有最大乘積 6。
示例 2:
輸入: [-2,0,-1]
輸出: 0
解釋: 結果不能為 2, 因為 [-2,-1] 不是子數組。

class Solution {
public:
    int maxProduct(vector<int>& nums) {
        if(nums.empty()) return 0;
        int len = nums.size();
        vector<vector<int>> data(len, vector<int>(2, 0));
        data[0][0] = nums[0];
        data[0][1] = nums[0];
        int maxVal = nums[0];
        for(int i = 1; i < len; i++)
        {
            if(nums[i] >= 0)
            {
                data[i][0] = max(nums[i]* data[i-1][0], nums[i]);
                data[i][1] = min(nums[i]* data[i-1][1], nums[i]);
            }
            else
            {
                data[i][0] = max(nums[i]* data[i-1][1], nums[i]);
                data[i][1] = min(nums[i]* data[i-1][0], nums[i]);
            }
            maxVal = data[i][0] > maxVal ? data[i][0] : maxVal;
        }
        return maxVal;
    }
};

題八:leetcode:322(零錢兌換)
(https://leetcode-cn.com/problems/coin-change/)
題目描述:
給定不同面額的硬幣 coins 和一個總金額 amount。編寫一個函數來計算可以湊成總金額所需的最少的硬幣個數。如果沒有任何一種硬幣組合能組成總金額,返回 -1。
示例 1:
輸入: coins = [1, 2, 5], amount = 11
輸出: 3
解釋: 11 = 5 + 5 + 1
示例 2:
輸入: coins = [2], amount = 3
輸出: -1

class Solution {
public:
    int coinChange(vector<int>& coins, int amount) {
        vector<int> data(amount+1, 0);
        for(int i = 1; i <= amount; i++)
        {
            int minVal = INT_MAX;
            for(int j = 0; j < coins.size(); j++)
            {
                if(i >= coins[j] && data[i-coins[j]] >= 0)
                {
                    minVal = min(minVal, data[i-coins[j]]+1);
                }  
            }
            data[i] = (minVal == INT_MAX ? -1 : minVal);
        }
        return data[amount];
    }
};

題九:leetcode:198(打家劫舍)
(https://leetcode-cn.com/problems/house-robber/)
題目描述:
你是一個專業的小偷,計劃偷竊沿街的房屋。每間房內都藏有一定的現金,影響你偷竊的唯一制約因素就是相鄰的房屋裝有相互連通的防盜系統,如果兩間相鄰的房屋在同一晚上被小偷闖入,系統會自動報警。
給定一個代表每個房屋存放金額的非負整數數組,計算你在不觸動警報裝置的情況下,能夠偷竊到的最高金額。
示例 1:
輸入: [1,2,3,1]
輸出: 4
解釋: 偷竊 1 號房屋 (金額 = 1) ,然后偷竊 3 號房屋 (金額 = 3)。
偷竊到的最高金額 = 1 + 3 = 4 。
示例 2:
輸入: [2,7,9,3,1]
輸出: 12
解釋: 偷竊 1 號房屋 (金額 = 2), 偷竊 3 號房屋 (金額 = 9),接著偷竊 5 號房屋 (金額 = 1)。
偷竊到的最高金額 = 2 + 9 + 1 = 12 。

class Solution {
public:
    int rob(vector<int>& nums) {
        if(nums.empty()) return 0;
        int len = nums.size();
        vector<int> data(len, 0);
        for(int i = 0; i < len; i++)
        {
            if(0 == i ) data[i] = nums[i];
            else if(1 == i) data[i] = max(nums[i], data[i-1]);
            else
            {
                data[i] = max(data[i-2]+nums[i], data[i-1]);
            }
        }
        return data[len-1];
    }
};

題十:leetcode:213(打家劫舍II)
(https://leetcode-cn.com/problems/house-robber-ii/)
題目描述:
你是一個專業的小偷,計劃偷竊沿街的房屋,每間房內都藏有一定的現金。這個地方所有的房屋都圍成一圈,這意味著第一個房屋和最后一個房屋是緊挨著的。同時,相鄰的房屋裝有相互連通的防盜系統,如果兩間相鄰的房屋在同一晚上被小偷闖入,系統會自動報警。
給定一個代表每個房屋存放金額的非負整數數組,計算你在不觸動警報裝置的情況下,能夠偷竊到的最高金額。
示例 1:
輸入: [2,3,2]
輸出: 3
解釋: 你不能先偷竊 1 號房屋(金額 = 2),然后偷竊 3 號房屋(金額 = 2), 因為他們是相鄰的。
示例 2:
輸入: [1,2,3,1]
輸出: 4
解釋: 你可以先偷竊 1 號房屋(金額 = 1),然后偷竊 3 號房屋(金額 = 3)。
偷竊到的最高金額 = 1 + 3 = 4 。

class Solution {
public:
    int subRob(vector<int>& nums) {
        if(nums.empty()) return 0;
        int len = nums.size();
        vector<int> data(len, 0);
        for(int i = 0; i < len; i++)
        {
            if(0 == i ) data[i] = nums[i];
            else if(1 == i) data[i] = max(nums[i], data[i-1]);
            else
            {
                data[i] = max(data[i-2]+nums[i], data[i-1]);
            }
        }
        return data[len-1];
    }
    int rob(vector<int>& nums) {
        if(nums.empty()) return 0;
        int len = nums.size();
        if(1 == len) return nums[0];
        vector<int> nums1 = nums;
        vector<int> nums2 = nums;
        nums1.erase(nums1.begin());
        nums2.erase(nums2.end() - 1);
        int val1 = subRob(nums1);
        int val2 = subRob(nums2);
        return max(val1, val2);
    }
};

題十一:leetcode:91(解碼方法)
https://leetcode-cn.com/problems/decode-ways/
題目描述:
一條包含字母 A-Z 的消息通過以下方式進行了編碼:
'A' -> 1
'B' -> 2
...
'Z' -> 26
給定一個只包含數字的非空字符串,請計算解碼方法的總數。
示例 1:
輸入: "12"
輸出: 2
解釋: 它可以解碼為 "AB"(1 2)或者 "L"(12)。
示例 2:
輸入: "226"
輸出: 3
解釋: 它可以解碼為 "BZ" (2 26), "VF" (22 6), 或者 "BBF" (2 2 6) 。

class Solution {
public:
    int numDecodings(string s) {
        if(s.empty()) return 0;
        int len = s.length();
        int last_1 = 1;  //最近一個
        int last_2 = 1;  //
        int ret = 0;
        if(s[0] == '0') return 0;
        else if(s[0] != '0') last_1 = 1;
        for(int i = 1;i < len; i++)
        {// 1 2 1 2 0
            int temp = last_1;
            if(isLastOneValid(s[i]) && isLastTwoValid(s[i-1], s[i])) ret = last_1 + last_2;
            else if(isLastOneValid(s[i]) && !isLastTwoValid(s[i-1], s[i])) ret = last_1;
            else if(!isLastOneValid(s[i]) && isLastTwoValid(s[i-1], s[i])) ret = last_2;
            else if(!isLastOneValid(s[i]) && !isLastTwoValid(s[i-1], s[i])) return 0;
            last_1 = ret;
            last_2 = temp;
            ret = 0;
        }
        return last_1;
    }
    bool isLastOneValid(char a)
    {
        if(a != '0') return true;
        else return false;
    }
    bool isLastTwoValid(char a, char b)
    {
        if(a == '1') return true;
        else if((a =='2') && (b <= '6' && b >= '0')) return true;
        else return false;
    }

};
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,578評論 6 544
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,701評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,691評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,974評論 1 318
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,694評論 6 413
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 56,026評論 1 329
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 44,015評論 3 450
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 43,193評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,719評論 1 336
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,442評論 3 360
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,668評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,151評論 5 365
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,846評論 3 351
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,255評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,592評論 1 295
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,394評論 3 400
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,635評論 2 380

推薦閱讀更多精彩內容