題一: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;
}
};