1,Triangle
1 int mininumTotal(vector<vector<int>>& triangle) { 2 for (int i = triangle.size() - 2; i >= 0; --i) { 3 for (int j = 0; j < i + 1; ++j) { 4 // 从下往上依次保存当前路径的最小值,上层只会用到下层的最小值 5 triangle[i][j] += min(triangle[i + 1][j], triangle[i + 1][j + 1]); 6 } 7 } 8 return triangle[0][0]; 9 }
2,Maximum SubArray
1 /* 2 * 状态转移方程为:f[j] = max{ f[j-1] + S[j],S[j] },其中 1 <= j <= n 3 * target = max{ f[j] },其中 1 <= j <= n 4 */ 5 int maxArray(vector<int>& nums) { 6 int n = nums.size(); 7 vector<int> dp(n + 1); 8 dp[0] = 0; 9 for (int i = 0; i < n; ++i) { 10 dp[i + 1] = max(dp[i] + nums[i], nums[i]); 11 } 12 return *max_element(dp.begin(), dp.end());
3,Palindromic Substrings
1 /* 2 * dp[i][j] 的值表示 s[i,j]这个字串是否为回文字符串 3 */ 4 int countSubstrings(string& s) { 5 int n = s.size(); 6 int res = 0; 7 vector<vector<bool>> dp(n, vector<bool>(n, false)); 8 for (int i = n - 1; i >= 0; i--) { 9 for (int j = i; j < n; ++j) { 10 dp[i][j] = (s[i] == s[j] && (j - i <= 2 || dp[i + 1][j - 1])); 11 if (dp[i][j]) res++; 12 } 13 } 14 return res; 15 }
4,Palindromic Substrings(II)
1 /* 2 * p[i][j]用来判断 s[i][j]这个字串是否是回文子串 3 * dp[i] 用来记录[0,i]这个范围内的最小切割数 4 * 所以只用求 dp[n-1] 的值就是答案 5 */ 6 int minCut(string& s) { 7 if (s.empty()) return 0; 8 int n = s.size(); 9 vector<vector<bool>> p(n, vector<bool>(n)); 10 vector<bool> dp(n); 11 12 for (int i = 0; i < n; ++i) { 13 dp[i] = i; // 对 dp[i]初始化为最大切割数 14 for (int j = 0; j <= i; ++j) { // 对每一个子串s[i][j]进行遍历 15 if (s[i] == s[j] && (i - j <= 2 || p[j + 1][i - 1])) { // 如果s[j][i] 为回文子串 16 p[j][i] = true; 17 dp[i] = (j == 0) ? 0 : min(dp[i], dp[j - 1] + 1); 18 } 19 } 20 } 21 return dp[n - 1]; 22 }
5,Longest Common Substring
1 /* 2 × 求解最长公共子串(一定是连续才称为子串) 3 × 初始化:dp[0][j] = 0;dp[i][0] = 0; 第0行全为0,第0列全为0 4 × 0 ; (i==0 || j==0) 5 * 状态转移方程: dp[i][j] = dp[i-1][j-1] + 1; (s1[i] == s2[j]) 6 * 0 ; (s1[i] != s2[j]) 7 × 结果:每次保存字符串长度的最大值即为所求 8 */ 9 int lcs(string s1,string s2) { 10 int len1 = s1.length(); 11 int len2 = s2.length(); 12 int res = 0; 13 vector<vector<int>> dp(len1+1,vector<int>(len2+1,0)); 14 15 for(int i=1;i<=len1;++i) { 16 for(int j=1;j<=len2;++j) { 17 if(s1[i-1] == s2[j-1]) dp[i][j] = dp[i-1][j-1] + 1; 18 res = max(res,dp[i][j]); 19 } 20 } 21 return res; 22 } 23 24 /* 25 * 求解最长公共子序列(不一定连续) 26 × 初始化:dp[0][j] = 0;dp[i][0] = 0; 27 * 0; (i == 0 || j == 0) 28 × 状态转移方程:dp[i][j] = dp[i-1][j-1] + 1; (s1[i] == s2[j]) 29 * max(dp[i-1][j],dp[i][j-1]);(s1[i] != s2[j]) 30 * 结果:最后保存的 dp[len1][len2] 即为所求 31 */ 32 int lcs(string s1,string s2) { 33 int len1 = s1.length(); 34 int len2 = s2.length(); 35 vector<vector<int>> dp(len1+1,vector<int>(len2+1,0)); 36 37 for(int i=1;i<=len1;++i) { 38 for(int j=1;j<=len2;++j) { 39 if(s1[i-1] == s2[j-1]) dp[i][j] = dp[i-1][j-1] + 1; 40 else dp[i][j] = max(dp[i-1][j],dp[i][j-1]); 41 } 42 } 43 return dp[len1][len2]; 44 } lcs
6: 最长连续递增序列
//LongestIncrSequence 最长连续递增序列 int LongestIncrSequence(vector<int> v) { int size = v.size(); int maxLen = 1;
//dp[i] 表示从下标 i 开始到末尾的最长连续递增序列 vector<int> dp(size, 1); for(int i=size-1; i>=0; i--) { for(int j=i+1; j<size; j++) { if(v[i] < v[j]) { dp[i] = max(dp[i], dp[j]+1); maxLen = max(maxLen, dp[i]); } } } return maxLen; }