5. Longest Palindromic Substring
题意:返回字符串的最长回文子串
我的思路:dp,http://blog.csdn.net/kangroger/article/details/37742639
我的代码:
class Solution { public: string longestPalindrome(string s) { int n = s.size(); if (n <= 1) return s; vectorint> > dp(n, vector<int>(n)); for (int i = 0; i < n; i++) for (int j = 0; j < n; j++) { if (i == j || (abs(i-j) == 1 && s[i] == s[j])) dp[i][j] = 1; else dp[i][j] = 0; } string ans = s.substr(0, 1); for (int l = 2; l <= n; l++) { for (int i = 0; i < n-l+1; i++) { int j = i+l-1; dp[i][j] = (s[i] == s[j]) ? dp[i+1][j-1] : 0; if (dp[i][j] == 1 && l > ans.size()) ans = s.substr(i, l); } } return ans; } };
solution解法:
class Solution { public: string longestPalindrome(string s) { if (s.empty()) return ""; if (s.size() == 1) return s; int min_start = 0, max_len = 1; for (int i = 0; i < s.size();) { if (s.size() - i <= max_len / 2) break; int j = i, k = i; while (k < s.size()-1 && s[k+1] == s[k]) ++k; // Skip duplicate characters. i = k+1; while (k < s.size()-1 && j > 0 && s[k + 1] == s[j - 1]) { ++k; --j; } // Expand. int new_len = k - j + 1; if (new_len > max_len) { min_start = j; max_len = new_len; } } return s.substr(min_start, max_len); } };
Manacher算法:http://www.cnblogs.com/grandyang/p/4475985.html
class Solution { public: string longestPalindrome(string s) { string t = "$#"; for (int i = 0; i < s.size(); ++i) { t += s[i]; t += "#"; } vector<int> p(t.size(), 0); int mx = 0, id = 0, resLen = 0, resCenter = 0; for (int i = 1; i < t.size(); ++i) { p[i] = mx > i ? min(p[2 * id - i], mx - i) : 1; while (t[i + p[i]] == t[i - p[i]]) ++p[i]; if (mx < i + p[i]) { mx = i + p[i]; id = i; } if (resLen < p[i]) { resLen = p[i]; resCenter = i; } } return s.substr((resCenter - resLen) / 2, resLen - 1); } };
10. Regular Expression Matching
题意:问b串能否匹配成a串,其中b串里的 ‘.’ 可以表示任意单一字符, ‘*’ 可以表示0个或任意多个他前边的字符
我的思路:dp,dp[i][j]表示a串的前i个字符与b串的前j个字符能否匹配,很垃圾的看了几眼discuss。。
我的代码:
class Solution { public: bool isMatch(string s, string p) { int m = s.size(), n = p.size(); vectorint> > dp(m+1, vector<int>(n+1, 0)); dp[0][0] = 1; for (int i = 0; i < n; i++) dp[0][i+1] = i > 0 && dp[0][i-1] && p[i] == '*'; for (int i = 0; i < m; i++) { for (int j = 0; j < n; j++) { if (s[i] == p[j] || p[j] == '.') dp[i+1][j+1] = dp[i][j]; else if (p[j] == '*') { dp[i+1][j+1] = dp[i+1][j-1] || (s[i] == p[j-1] || p[j-1] == '.') && dp[i][j+1]; } else dp[i+1][j+1] = 0; } } return dp[m][n]; } };
32. Longest Valid Parentheses
题意:给定一组小括号序列,求括号合法的最长连续子串的长度
思路:
1)栈解法
class Solution { public: int longestValidParentheses(string s) { stack<int> sk; int n = s.size(), ans = 0, start = 0; for (int i = 0; i < n; i++) { if (s[i] == '(') sk.push(i); else { if (sk.empty()) start = i+1; else { sk.pop(); ans = sk.empty() ? max(ans, i-start+1) : max(ans, i-sk.top()); } } } return ans; } };
2)DP解法
class Solution { public: int longestValidParentheses(string s) { int n = s.size(), ans = 0; vector<int> dp(n, 0); for (int i = n-2; i >= 0; i--) { if (s[i] == '(') { int tail = i+dp[i+1]+1; if (tail < n && s[tail] == ')') { dp[i] = dp[i+1]+2; if (tail+1 < n) dp[i] += dp[tail+1]; } } ans = max(ans, dp[i]); } return ans; } };
44. Wildcard Matching
题意:匹配串,第10题稍作改动即可
我的代码:
class Solution { public: bool isMatch(string s, string p) { int m = s.size(), n = p.size(); vectorint> > dp(m+1, vector<int>(n+1, 0)); dp[0][0] = 1; for (int i = 0; i < n; i++) dp[0][i+1] = dp[0][i] && p[i] == '*'; for (int i = 0; i < m; i++) { for (int j = 0; j < n; j++) { if (s[i] == p[j] || p[j] == '?') dp[i+1][j+1] = dp[i][j]; else if (p[j] == '*') { dp[i+1][j+1] = dp[i+1][j] || dp[i][j+1]; } else dp[i+1][j+1] = 0; } } return dp[m][n]; } };
solution解法:
class Solution { public: bool isMatch(string s, string p) { int slen = s.size(), plen = p.size(), i, j, iStar=-1, jStar=-1; for(i=0,j=0 ; ij) { if(p[j]=='*') { //meet a new '*', update traceback i/j info iStar = i; jStar = j; --i; } else { if(p[j]!=s[i] && p[j]!='?') { // mismatch happens if(iStar >=0) { // met a '*' before, then do traceback i = iStar++; j = jStar; } else return false; // otherwise fail } } } while(p[j]=='*') ++j; return j==plen; } };
85. Maximal Rectangle
题意:给定一个01二维矩阵,输出最大矩形1面积
思路:http://blog.csdn.net/makuiyu/article/details/44857479
我的代码:
解法一
class Solution { public: int largestRectangleArea(vector<int>& heights) { heights.push_back(-1); int i = 0, n = heights.size(), ans = 0; stack<int> loc; while (i < n) { if (loc.empty() || heights[loc.top()] <= heights[i]) { loc.push(i++); } else { int tmp = loc.top(); loc.pop(); int l = loc.empty() ? 0 : loc.top()+1; ans = max(ans, heights[tmp]*(i-l)); } } return ans; } int maximalRectangle(vectorchar>>& matrix) { if (matrix.size() == 0) return 0; int ans = 0; int m = matrix.size(), n = matrix[0].size(); vector<int> h(n, 0); for (int i = 0; i < m; i++) { for (int j = 0; j < n; j++) { if (matrix[i][j] == '0') h[j] = 0; else h[j]++; } ans = max(ans, largestRectangleArea(h)); } return ans; } };
解法二
class Solution { public: int maximalRectangle(vectorchar>>& matrix) { if (matrix.size() == 0 || matrix[0].size() == 0) return 0; int ans = 0, m = matrix.size(), n = matrix[0].size(); vector<int> h(n, 0), l(n, 0), r(n, n); for (int i = 0; i < m; i++) { int cur_l = 0, cur_r = n; //左闭右开 for (int j = n-1; j >= 0; j--) { r[j] = matrix[i][j] == '1' ? min(r[j], cur_r) : n; cur_r = matrix[i][j] == '1' ? cur_r : j; } for (int j = 0; j < n; j++) { h[j] = matrix[i][j] == '1' ? h[j]+1 : 0; l[j] = matrix[i][j] == '1' ? max(l[j], cur_l) : 0; cur_l = matrix[i][j] == '1' ? cur_l : j+1; ans = max(ans, h[j]*(r[j]-l[j])); } } return ans; } };
87. Scramble String
题意:问两个字符串能否由写成二叉树后翻转节点得到
我的思路:http://blog.csdn.net/makuiyu/article/details/44926439
我的代码:
class Solution { public: bool isScramble(string s1, string s2) { if (s1.size() != s2.size()) return 0; int n = s1.size(); vectorint> > > dp(n, vector int> >(n, vector<int>(n+1, 0))); for (int i = 0; i < n; i++) for (int j = 0; j < n; j++) dp[i][j][1] = s1[i] == s2[j]; for (int l = 2; l <= n; l++) for (int i = 0; i <= n-l; i++) for (int j = 0; j <= n-l; j++) for (int k = 1; k < l; k++) dp[i][j][l] = dp[i][j][l] || dp[i+k][j+k][l-k] && dp[i][j][k] || dp[i][j+l-k][k] && dp[i+k][j][l-k]; return dp[0][0][n]; } };
91. Decode Ways
题意:将A~Z编码成1~26,给定一串数字,求有多少种解码方式
我的思路:简单dp,1*或者21~26可以由隔一个来,其他的只能由前一个来(整十特例支能友隔一个来)
我的代码:
class Solution { public: int numDecodings(string s) { int n = s.size(); if (n == 0 || s[0] == '0') return 0; vector<int> dp(n+1); dp[0] = dp[1] = 1; for (int i = 1; i < n; i++) { if (s[i] != '0') dp[i+1] = dp[i]; if (s[i-1] == '1' || s[i-1] == '2' && s[i] <= '6') dp[i+1] += dp[i-1]; } return dp[n]; } };
优化:dp没必要开那么大,只留前两个值就可以
96. Unique Binary Search Trees
题意:求整数1~n能形成的二叉查找树的数目
我的思路:递归实现的分治,左右子树的数目相乘求和
我的代码:
class Solution { public: int dfs(int n) { int ans = 0; if (n <= 1) return 1; for (int i = 0; i < n/2; i++) ans += dfs(i)*dfs(n-1-i)*2; if (n%2) ans += pow(dfs(n/2), 2); return ans; } int numTrees(int n) { return dfs(n); } };
九章最优解:dp,两重循环
class Solution { public: /** * @paramn n: An integer * @return: An integer */ int numTrees(int n) { // write your code here int f[n + 1]; memset(f, 0, sizeof(int) * (n + 1)); f[0] = 1; for (int i = 1; i <= n; i++) { for (int j = 0; j < i; j++) { f[i] += f[j] * f[i - 1 - j]; } } return f[n]; } };
97. Interleaving String
题意:判断一个字符串能不能由两个字符串按照他们自己的顺序,每次挑取两个串中的一个字符来构造出来。、
我的思路:比较简单的一个dp,把两个字符串作为横纵坐标看成棋盘,则目标就是判断能否从左上角走到右下角
我的代码:
class Solution { public: bool isInterleave(string s1, string s2, string s3) { int m = s1.size(), n = s2.size(), k = s3.size(); if (k != m+n) return 0; if (m == 0) return s2 == s3; if (n == 0) return s1 == s3; vectorint> > dp(m+1, vector<int>(n+1, 0)); dp[0][0] = 1; for (int i = 1; i <= n; i++) dp[0][i] = dp[0][i-1] && (s3[i-1] == s2[i-1]); for (int i = 1; i <= m; i++) dp[i][0] = dp[i-1][0] && (s3[i-1] == s1[i-1]); for (int i = 1; i <= m; i++) for (int j = 1; j <= n; j++) dp[i][j] = dp[i][j-1] && (s3[i+j-1] == s2[j-1]) || dp[i-1][j] && (s3[i+j-1] == s1[i-1]); return dp[m][n]; } };
120. Triangle
题意:给定一个三角形二维数组,输出从上到下最小和,路径只能往左下、右下最近的走
我的思路:基础dp,大白书上第一道dp题
我的代码:
class Solution { public: int minimumTotal(vectorint>>& triangle) { for (int i = triangle.size()-2; i >= 0; i--) for (int j = 0; j <= i; j++) triangle[i][j] += min(triangle[i+1][j], triangle[i+1][j+1]); return triangle[0][0]; } };
九章最优解:他是从上往下加和,不如从下往上走的好
class Solution { public: /** * @param triangle: a list of lists of integers. * @return: An integer, minimum path sum. */ int minimumTotal(vectorint> > &triangle) { // write your code here if (triangle.size() == 0) return 0; vector<int> f(triangle[triangle.size()-1].size()); f[0] = triangle[0][0]; for(int i = 1; i < triangle.size(); i++) for(int j = triangle[i].size() - 1; j >= 0; j--) if (j == 0) f[j] = f[j] + triangle[i][j]; else if (j == triangle[i].size() - 1) f[j] = f[j-1] + triangle[i][j]; else f[j] = min(f[j-1], f[j]) + triangle[i][j]; int ret = INT_MAX; for(int i = 0; i < f.size(); i++) ret = min(ret, f[i]); return ret; } };
121. Best Time to Buy and Sell Stock
题意:给定一个数组表示股票价格,限制一天买一天卖(可以是同一天),输出最大盈利
我的思路:维护一个dp值表示某天以前的最小值,在按天更新差值,巨水dp
我的代码:
class Solution { public: int maxProfit(vector<int>& prices) { if (prices.size() == 0) return 0; int ans = 0, dp = prices[0]; for (int i = 1; i < prices.size(); i++) { dp = min(dp, prices[i]); ans = max(ans, prices[i]-dp); } return ans; } };
九章最优解:一样
class Solution { public: /** * @param prices: Given an integer array * @return: Maximum profit */ int maxProfit(vector<int> &prices) { // write your code here if (prices.empty()) return 0; int i=prices.size()-1, ans=0, maxp=prices[i]; for (--i; i>=0; --i){ ans=max(ans, maxp-prices[i]); maxp=max(maxp, prices[i]); } return ans; } };
123. Best Time to Buy and Sell Stock III
题意:卖股票,最多两次交易,求最大收益
我的思路:两种解法:http://blog.csdn.net/u012501459/article/details/46514309
我的代码:
1)
class Solution { public: int maxProfit(vector<int>& prices) { int n = prices.size(); if (n <= 1) return 0; vector<int> dp1(n, 0), dp2(n, 0); int ans, minn = prices[0], maxn = prices[n-1]; for (int i = 1; i < n; i++) { minn = min(minn, prices[i]); dp1[i] = max(dp1[i-1], prices[i]-minn); } ans = dp1[n-1]; for (int i = n-2; i >= 0; i--) { maxn = max(maxn, prices[i]); dp2[i] = max(dp2[i+1], maxn-prices[i]); ans = max(ans, dp1[i]+dp2[i+1]); } return ans; } };
2)solution
132. Palindrome Partitioning II
题意:给定一个字符串,最少劫几次使得各子串都是回文串
我的思路:
1)dp,pal[i][j]表示s[i]~s[j]是否是回文串,dp[i]表示s[i]~s[n-1]的最小cut数,当j==n-1且s[i~j]是回文串时,dp[i] = 0,否则当s[i~j]是回文串时,更新dp[i]为min(dp[i], dp[j+1]+1)
我的代码:
class Solution { public: int minCut(string s) { if (s.size() == 0) return 0; int n = s.size(); vectorbool> > pal(n, vector<bool>(n, 0)); vector<int> dp(n); for (int i = n-1; i >= 0; i--) { dp[i] = n-1-i; for (int j = i; j < n; j++) { if (s[i] == s[j] && (j-i < 2 || pal[i+1][j-1])) { pal[i][j] = 1; if (j == n-1) dp[i] = 0; else dp[i] = min(dp[i], dp[j+1]+1); } } } return dp[0]; } };
2)solution,绝了,从一点往外扩来判断回文
代码:
class Solution { public: int minCut(string s) { int n = s.size(); vector<int> cut(n+1, 0); // number of cuts for the first k characters for (int i = 0; i <= n; i++) cut[i] = i-1; for (int i = 0; i < n; i++) { for (int j = 0; i-j >= 0 && i+j < n && s[i-j]==s[i+j] ; j++) // odd length palindrome cut[i+j+1] = min(cut[i+j+1],1+cut[i-j]); for (int j = 1; i-j+1 >= 0 && i+j < n && s[i-j+1] == s[i+j]; j++) // even length palindrome cut[i+j+1] = min(cut[i+j+1],1+cut[i-j+1]); } return cut[n]; } };
139. Word Break
题意:给定一个字典,判断串s能否由字典里的词组成、
我的思路:dp
我的代码:
class Solution { public: bool wordBreak(string s, vector<string>& wordDict) { int n = s.size(); vector<int> dp(n+1, 0); dp[0] = 1; for (int i = 0; i < n; i++) for (int j = 1; j <= n+1-i; j++) dp[i+j] = dp[i+j] | ((find(wordDict.begin(), wordDict.end(), s.substr(i, j)) != wordDict.end()) ? dp[i] : 0); return dp[n]; } };
140. Word Break II
题意:将一个字符串分成各个单词相连,给定字典,输出所有情况
我的思路:dfs+记忆化搜素,map记录下已经找过的情况
我的代码:
class Solution { public: unordered_map<string, vector<string>> m; vector<string> wordBreak(string s, vector<string>& wordDict) { if (m.find(s) != m.end()) return m[s]; vector<string> ans; if (find(wordDict.begin(), wordDict.end(), s) != wordDict.end()) ans.push_back(s); for (int l = 1; l < s.size(); l++) { string tmp = s.substr(0, l); if (find(wordDict.begin(), wordDict.end(), tmp) != wordDict.end()) { vector<string> gg, hehe = wordBreak(s.substr(l, s.size()-l), wordDict); for (int i = 0; i < hehe.size(); i++) gg.push_back(tmp+' '+hehe[i]); ans.insert(ans.end(),gg.begin(), gg.end()); } } m[s] = ans; return ans; } };
152. Maximum Product Subarray
题意:求数组的最大子串积
我的思路:保存两个dp变量分别为以nums[i]结尾的最大正数积和最小负数积,分别更新这两个变量,返回最大的最大正数积即可
我的代码:
class Solution { public: int maxProduct(vector<int>& nums) { int ans = nums[0], maxn = nums[0] > 0 ? nums[0] : 0, minn = nums[0] < 0 ? nums[0] : 0; for (int i = 1; i < nums.size(); i++) { int tmp1 = nums[i] > 0 ? maxn*nums[i] : minn*nums[i]; int tmp2 = nums[i] > 0 ? minn*nums[i] : maxn*nums[i]; maxn = max(tmp1, nums[i]); minn = min(tmp2, nums[i]); ans = max(ans, maxn); } return ans; } };
九章最优解:思路一样,他两个dp变量是两个数组,没有必要
class Solution { public: /** * @param nums: a vector of integers * @return: an integer */ int maxProduct(vector<int>& nums) { // write your code here vector<int> f, g; f.push_back(nums[0]); g.push_back(nums[0]); for (int i=1; ii) { f.push_back(max(max(f[i-1]*nums[i], g[i-1]*nums[i]), nums[i])); g.push_back(min(min(f[i-1]*nums[i], g[i-1]*nums[i]), nums[i])); } int m = f[0]; for (int i=1; i max(m, f[i]); return m; } };
174. Dungeon Game
题意:给定一个二维数组,每个数表示到这个位置要减去或者加上的值,求从左上到右下初始值最少是多少?只能往右或往下走,过程中值不能小于等于0
我的思路:dp,dp[i][j]表示这个位置最少需要多少值,从右下往左上推
我的代码:
class Solution { public: int calculateMinimumHP(vectorint>>& dungeon) { int m = dungeon.size(), n = dungeon[0].size(); vector int>> dp(m+1, vector<int>(n+1, 0x7fffffff)); dp[m][n-1] = dp[m-1][n] = 1; for (int i = m-1; i >= 0; i--) for (int j = n-1; j >= 0; j--) dp[i][j] = (min(dp[i][j+1], dp[i+1][j]) > dungeon[i][j] ? min(dp[i][j+1], dp[i+1][j])-dungeon[i][j] : 1); return dp[0][0]; } };
188. Best Time to Buy and Sell Stock IV
题意:给定一组股票价格,输出最多k次交易约束下的最大收益
我的思路:123题解法二
我的代码:
class Solution { public: int maxProfit(int k, vector<int>& prices) { k = min(k, (int)prices.size()); if (k == 0) return 0; vector<int> buy(k, 0x80000000); vector<int> sell(k, 0); for (int i = 0; i < prices.size(); i++) { for (int j = k-1; j >= 0; j--) { sell[j] = max(sell[j], buy[j]+prices[i]); buy[j] = (j > 0 ? max(buy[j], sell[j-1]-prices[i]) : max(buy[j], -prices[i])); } } return sell[k-1]; } };
198. House Robber
题意:给定一个数组取数,不能取连续的两个,求取出的最大和
我的思路:简单dp,dp[i] = max(dp[i-2]+nums[i], dp[i-1])
我的代码:
class Solution { public: int rob(vector<int>& nums) { if (nums.size() == 0) return 0; if (nums.size() > 1) nums[1] = max(nums[0], nums[1]); for (int i = 2; i < nums.size(); i++) nums[i] = max(nums[i-2]+nums[i], nums[i-1]); return nums[nums.size()-1]; } };
九章最优解:思路一样,写法不同
class Solution { public: /** * @param A: An array of non-negative integers. * return: The maximum amount of money you can rob tonight */ long long houseRobber(vector<int> A) { // write your code here long long result = 0; long long f = 0, g = 0, f1 = 0, g1 = 0; int len = A.size(); for (int i = 0; i < len; ++i) { f1 = g + A[i]; g1 = max(f, g); g = g1, f = f1; } return max(g, f); } };
213. House Robber II
题意:数组是环形的,其余跟上题一样
我的思路:两遍上题的dp,一种是nums[0]~nums[n-2],一种是nums[1]~nums[n-1],两种分别代表了有无第一间房,两者取大的
我的代码:
class Solution { public: int rob(vector<int>& nums) { if (nums.size() == 0) return 0; if (nums.size() == 1) return nums[0]; vector<int> nums2(nums); if (nums.size() > 1) nums[1] = max(nums[0], nums[1]); for (int i = 2; i < nums.size()-1; i++) nums[i] = max(nums[i-2]+nums[i], nums[i-1]); nums2[0] = 0; for (int i = 2; i < nums.size(); i++) nums2[i] = max(nums2[i-2]+nums2[i], nums2[i-1]); return max(nums[nums.size()-2], nums2[nums.size()-1]); } };
九章最优解:思路是一样的,写法不一样
class Solution { public: /** * @param nums: An array of non-negative integers. * return: The maximum amount of money you can rob tonight */ int houseRobber2(vector<int>& nums) { // write your code here int n = nums.size(); if (n == 0) return 0; if (n == 1) return nums[0]; vector<int> dp(n); dp[0] = 0; dp[1] = nums[1]; for (int i = 2; i < n; ++i) dp[i] = max(dp[i - 2] + nums[i], dp[i - 1]); int answer = dp[n - 1]; dp[0] = nums[0]; dp[1] = max(dp[0], nums[1]); for (int i = 2; i < n; ++i) dp[i] = max(dp[i - 2] + nums[i], dp[i - 1]); return max(dp[n - 2], answer); } };
221. Maximal Square
题意:给定01二维数组,输出最大的1构成的正方形面积
我的思路:85题法一改一点就可以用,但是时间不好
我的代码:
class Solution { public: int largestRectangleArea(vector<int>& heights) { heights.push_back(-1); int i = 0, n = heights.size(), ans = 0; stack<int> loc; while (i < n) { if (loc.empty() || heights[loc.top()] <= heights[i]) { loc.push(i++); } else { int tmp = loc.top(); loc.pop(); int l = loc.empty() ? 0 : loc.top()+1; ans = max(ans, min(heights[tmp], (i-l))*min(heights[tmp], (i-l))); } } return ans; } int maximalSquare(vectorchar>>& matrix) { if (matrix.size() == 0) return 0; int ans = 0; int m = matrix.size(), n = matrix[0].size(); vector<int> h(n, 0); for (int i = 0; i < m; i++) { for (int j = 0; j < n; j++) { if (matrix[i][j] == '0') h[j] = 0; else h[j]++; } ans = max(ans, largestRectangleArea(h)); } return ans; } };
solution解法:
P[0][j] = matrix[0][j]
(topmost row);P[i][0] = matrix[i][0]
(leftmost column);- For
i > 0
andj > 0
: ifmatrix[i][j] = 0
,P[i][j] = 0
; ifmatrix[i][j] = 1
,P[i][j] = min(P[i - 1][j], P[i][j - 1], P[i - 1][j - 1]) + 1
class Solution { public: int maximalSquare(vectorchar>>& matrix) { if (matrix.empty()) return 0; int m = matrix.size(), n = matrix[0].size(), pre, ans = 0; vector<int> dp(n+1, 0); for (int i = 0; i < m; i++) { pre = 0; for (int j = 1; j <= n; j++) { int tmp = dp[j]; if (matrix[i][j-1] == '1') { dp[j] = min(dp[j], min(dp[j-1], pre))+1; ans = max(ans, dp[j]); } else dp[j] = 0; pre = tmp; } } return ans*ans; } };
279. Perfect Squares
题意:输出n最少可由几个平方数求和得到
我的思路:dp递推
我的代码:
class Solution { public: int numSquares(int n) { vector<int> num(n+1, 0); for (int i = 0; i <= n; i++) if (i == 0 || num[i] > 0) for (int j = 1; i+j*j <= n; j++) num[i+j*j] = num[i+j*j] == 0 ? num[i]+1 : min(num[i+j*j], num[i]+1); return num[n]; } };
九章最优解:三种解法,我的是最平常的。。还看不明白。。
// version 1 class Solution { public: /** * @param n a positive integer * @return an integer */ int numSquares(int n) { // Write your code here vector<int> dp{ 0 }; dp.resize(n + 1, INT_MAX); for (int i = 1, k; (k = i * i) <= n; ++i) for (int j = k; j <= n; ++j) if (dp[j] > dp[j - k] + 1) dp[j] = dp[j - k] + 1; return dp[n]; } }; // version 2 Math class Solution { public: /** * @param n a positive integer * @return an integer */ int numSquares(int n) { // Write your code here int ub = sqrt(n); for (int a = 0; a <= ub; ++a) { for (int b = a; b <= ub; ++b) { int c = sqrt(n - a * a - b * b); if (a * a + b * b + c * c == n) return !!a + !!b + !!c; } } return 4; } }; // version 3 Math II class Solution { public: /** * @param n a positive integer * @return an integer */ int numSquares(int n) { // Write your code here while (n % 4 == 0) n /= 4; if (n % 8 == 7) return 4; for (int i = 0; i * i <= n; ++i) { int j = sqrt(n - i * i); if (i * i + j * j == n) return !!i + !!j; } return 3; } };
300. Longest Increasing Subsequence
题意:最长上升子序列裸题
我的思路:大白书P62,掌握O(nlogn)的写法
class Solution { public: int lengthOfLIS(vector<int>& nums) { int n = nums.size(); if (n == 0) return 0; vector<int> g(n+1, 0x7fffffff); vector<int> d(n); for (int i = 0; i < n; i++) { int k = lower_bound(g.begin()+1, g.end(), nums[i])-g.begin(); d[i] = k; g[k] = nums[i]; } for (int i = 1; i < n; i++) d[i] = max(d[i], d[i-1]); return d[n-1]; } };
九章最优解:O(n^2)的次优解
303. Range Sum Query - Immutable
题意:输出数组[i,j]元素之和
我的思路:大水题
我的代码:
class NumArray { public: vector<int> sum; NumArray(vector<int> nums) { sum.resize(nums.size()+1, 0); for (int i = 1; i <= nums.size(); i++) sum[i] = sum[i-1]+nums[i-1]; } int sumRange(int i, int j) { return sum[j+1]-sum[i]; } };
304. Range Sum Query 2D - Immutable
题意:给定一个矩阵和左上右下两个点下标,求小矩阵中的值之和
我的思路:sum[i][j]表示第i行[0, j]元素之和
我的代码:
class NumMatrix { public: vectorint>> sum; NumMatrix(vector int>> matrix) { int m = matrix.size(); if (m > 0) { int n = matrix[0].size(); sum.resize(m); for (int i = 0; i < m; i++) sum[i].resize(n); for (int i = 0; i < m; i++) for (int j = 0; j < n; j++) sum[i][j] = (j == 0 ? matrix[i][j] : matrix[i][j]+sum[i][j-1]); } } int sumRegion(int row1, int col1, int row2, int col2) { int ans = 0; for (int i = row1; i <= row2; i++) ans += (col1 == 0 ? this->sum[i][col2] : this->sum[i][col2]-this->sum[i][col1-1]); return ans; } }; /** * Your NumMatrix object will be instantiated and called as such: * NumMatrix obj = new NumMatrix(matrix); * int param_1 = obj.sumRegion(row1,col1,row2,col2); */
九章最优解:dp[i][j]表示元素[i][j]左上角的元素之和
class NumMatrix { private: vectorint>> dp; public: NumMatrix(vector int>> matrix) { if (matrix.size() == 0 || matrix[0].size() == 0) { return; } int n = matrix.size(); int m = matrix[0].size(); dp.resize(n + 1, vector<int>(m + 1, 0)); for (int r = 0; r < n; r++) { for (int c = 0; c < m; c++) { dp[r + 1][c + 1] = dp[r + 1][c] + dp[r][c + 1] + matrix[r][c] - dp[r][c]; } } } int sumRegion(int row1, int col1, int row2, int col2) { return dp[row2 + 1][col2 + 1] - dp[row1][col2 + 1] - dp[row2 + 1][col1] + dp[row1][col1]; } };
309. Best Time to Buy and Sell Stock with Cooldown
题意:任意次股票买卖,有冷却期(卖出后至少一天不可以买入),求最大收益
思路:https://www.cnblogs.com/grandyang/p/4997417.html
代码:
class Solution { public: int maxProfit(vector<int>& prices) { int buy = 0x80000000, buy_pre = 0, sell = 0, sell_pre = 0; for (int i = 0; i < prices.size(); i++) { buy_pre = buy; buy = max(sell_pre-prices[i], buy_pre); sell_pre = sell; sell = max(buy_pre+prices[i], sell_pre); } return sell; } };
312. Burst Balloons
题意:每次打破一个气球,获得他的值与左右两个数的乘积,依次打破所有气球(顺序自定,打破之后它左右两个变为相邻),求获得的最大值
思路:discuss第一个,dp[i][j]为从i到j的气球打完获得的最大值,着眼于最后打破的那个,dp[left][right] = max(dp[left][right], nums[left] * nums[i] * nums[right] + dp[left][i] + dp[i][right]);
我的代码:
class Solution { public: int maxCoins(vector<int>& nums) { nums.insert(nums.begin(), 1); nums.insert(nums.end(), 1); int n = nums.size(); vectorint>> dp(n, vector<int>(n, 0)); for (int k = 2; k < n; k++) for (int i = 0; i < n-k; i++) for (int j = i+1; j < i+k; j++) dp[i][i+k] = max(dp[i][i+k], dp[i][j]+dp[j][i+k]+nums[i]*nums[j]*nums[i+k]); return dp[0][n-1]; } };
322. Coin Change
题意:给定一组硬币面值和一个总价,求组成总价最少需要多少硬币,不能组成返回-1
我的思路:简单dp
我的代码:
class Solution { public: int coinChange(vector<int>& coins, int amount) { vector<int> num(amount+1, amount+1); num[0] = 0; for (int i = 1; i <= amount; i++) for (int j = 0; j < coins.size(); j++) if (i-coins[j] >= 0) num[i] = min(num[i], num[i-coins[j]]+1); return num[amount] > amount ? -1 : num[amount]; } };
solution解法:我的是解法三
https://leetcode.com/problems/coin-change/solution/
334. Increasing Triplet Subsequence
题意:判断是否有长度为3的上升子序列(可以不挨着)
我的思路:根据题300求上升子串长度,大于等于3时返回1
我的代码:
class Solution { public: bool increasingTriplet(vector<int>& nums) { int n = nums.size(); if (n == 0) return 0; vector<int> g(n+1, 0x7fffffff); vector<int> d(n); for (int i = 0; i < n; i++) { int k = lower_bound(g.begin()+1, g.end(), nums[i])-g.begin(); d[i] = k; if (d[i] >= 3) return 1; g[k] = nums[i]; } //for (int i = 1; i < n; i++) d[i] = max(d[i], d[i-1]); return 0; } };
九章最优解:不用那么麻烦,记录上升三个数的前两个,扫一遍,大于谁更新谁,同时大于两个即返回1
class Solution { public: bool increasingTriplet(vector<int>& nums) { if (nums.size() < 3) return false; vector<int> ans(2, INT_MAX); for (int now : nums) { if (now <= ans[0]) { ans[0] = now; } else if (now <= ans[1]) { ans[1] = now; } else { return true; } } return false; } };
343. Integer Break
题意:将正一个整数拆分为至少两个正整数之和,使他们的和最大
我的思路:dp,但是当一个数拆分为另两个数a, b时,既可能是a,b本身,也可能是dp[a],dp[b],共四种情况
我的代码:
class Solution { public: int integerBreak(int n) { vector<int> dp(n+1, 0); dp[1] = 1; for (int i = 2; i <= n; i++){ for (int j = 1; j <= i/2; j++) { dp[i] = max(dp[i], j*(i-j)); dp[i] = max(dp[i], j*dp[i-j]); dp[i] = max(dp[i], dp[j]*(i-j)); dp[i] = max(dp[i], dp[j]*dp[i-j]); } } return dp[n]; } };
354. Russian Doll Envelopes
题意:给定一组信封的长宽,长和宽都较小(没有等于,不能翻转)的信封可以放入较大的信封里,求最多可以嵌套多少个信封(顺序不一定是输入顺序)
我的思路:将一维从小到大排序后即可按照最长上升子序列来做了,但是有一个非常good的点是,将第二维从大到小排序,再套LCS的模板,即可避免第一维相等的问题
我的代码:记住sort函数cmp的写法
class Solution { public: static bool cmp(const pair<int, int>& x, pair<int, int>& y) { return x.first != y.first ? x.first < y.first : x.second > y.second; } int maxEnvelopes(vectorint, int>>& envelopes) { int n = envelopes.size(); if (n == 0) return 0; sort(envelopes.begin(), envelopes.end(), cmp); vector<int> dp(n); vector<int> g(n+1, 0x7fffffff); for (int i = 0; i < n; i++) { int k = lower_bound(g.begin()+1, g.end(), envelopes[i].second)-g.begin(); dp[i] = k; g[k] = envelopes[i].second; } for (int i = 1; i < n; i++) dp[i] = max(dp[i], dp[i-1]); return dp[n-1]; } };
九章最优解:一样
bool cmp(const pair<int,int>&x, const pair<int, int>&y) { return x.first != y.first ? x.first < y.first : x.second > y.second; } class Solution { public: /** * @param envelopes a number of envelopes with widths and heights * @return the maximum number of envelopes */ int maxEnvelopes(vectorint, int>>& envelopes) { // Write your code here int n = envelopes.size(); if (n == 0) { return 0; } sort(envelopes.begin(), envelopes.end(), cmp); vector<int> dp(n), height(n+1, INT_MAX); for (int i = 0; i < n; i++) { int k = lower_bound(height.begin(), height.end(), envelopes[i].second) - height.begin() ; dp[i] = k; height[k] = envelopes[i].second; } int ans = 0; for (int i = 0; i < n; i++) { ans = max(ans, dp[i]); } return ans + 1; } };
363. Max Sum of Rectangle No Larger Than K
题意:输出不超过k的最大子矩阵和
我的思路:最大子矩阵和+小于k的最大字段和问题,看过两个链接就很简单了https://leetcode.com/problems/max-sum-of-rectangle-no-larger-than-k/discuss/83599
我的代码:
class Solution { public: vectorint>> transpos(vector int>>& matrix) { int m = matrix.size(), n = matrix[0].size(); if (m <= n) return matrix; vector int>> ret(n, vector<int>(m)); for (int i = 0; i < n; i++) for (int j = 0; j < m; j++) ret[i][j] = matrix[j][i]; return ret; } int maxSumSubmatrix(vector int>>& matrix, int k) { vector int>> s = transpos(matrix); int m = s.size(), n = s[0].size(), maxsum = 0x80000000; for (int i = 0; i < m; i++) { vector<int> sum(n, 0); for (int j = i; j < m; j++) { for (int kk = 0; kk < n; kk++) sum[kk] += s[j][kk]; set<int> cumset; cumset.insert(0); int best = 0x80000000, cum = 0; for(int kk = 0;kk < n; kk++) { cum += sum[kk]; set<int>::iterator sit = cumset.lower_bound(cum-k); if(sit != cumset.end()) best = max(best, cum-*sit); cumset.insert(cum); } maxsum = max(maxsum, best); } } return maxsum; } };
368. Largest Divisible Subset
题意:求数组的最大子集,其中每对数字都可以整除
我的思路:dp,最长上升子串变体
我的代码:
class Solution { public: vector<int> largestDivisibleSubset(vector<int>& nums) { int n = nums.size(), maxn = 1, k = 0; if (n == 0) return {}; vector<int> dp(n, 1), loc(n), ans; sort(nums.begin(), nums.end()); for (int i = 0; i < n; i++) for (int j = 0; j < i; j++) if (nums[i]%nums[j] == 0 && dp[j]+1 > dp[i]) { dp[i] = dp[j]+1; loc[i] = j; if (dp[i] > maxn) { maxn = dp[i]; k = i; } } while (maxn--) { ans.push_back(nums[k]); k = loc[k]; } return ans; } };
375. Guess Number Higher or Lower II
题意:猜数,告诉高或者低,猜错罚相应点数,求最少需要准备多少点数可以猜出任意数
我的思路:记忆化搜索
我的代码:
class Solution { public: int hehe(vectorint>>& dp, int l, int r) { if (l >= r) return 0; if (dp[l][r]) return dp[l][r]; int ans = 0x7fffffff; for (int i = l; i <= r; i++) ans = min(ans, i+max(hehe(dp, l, i-1),hehe(dp, i+1, r))); dp[l][r] = ans; return ans; } int getMoneyAmount(int n) { vector int>> dp(n+1, vector<int>(n+1, 0)); return hehe(dp, 1, n); } };
solution解法:自底向上循环
class Solution { int max(int a,int b) { return a>b?a:b; } public: int getMoneyAmount(int n) { vectorint>> dp(n+1,vector<int>(n+1,0)); for(int i=2;i<=n;++i) { for(int j=i-1;j>0;--j) { int global_min = INT_MAX; for(int k=j+1;kk) { int tmp=k+max(dp[j][k-1],dp[k+1][i]); if(tmp tmp; } dp[j][i]=j+1==i?j:global_min; } } return dp[1][n]; } };
377. Combination Sum IV
题意:给定一个数组和一个和,数组元素不重复,求数组元素可反复使用情况下有多少种情况可以加得此和
我的思路:递推,类似走楼梯那题
我的代码:
class Solution { public: int combinationSum4(vector<int>& nums, int target) { vector<int> ans(target+1, 0); ans[0] = 1; for (int i = 1; i <= target; i++) for (int j = 0; j < nums.size(); j++) if (i-nums[j] >= 0) ans[i] += ans[i-nums[j]]; return ans[target]; } };
九章最优解:完全一样
416. Partition Equal Subset Sum
题意:给定一个数组,问能否放成两堆(任意放,不是左右划分)使他们元素之和相等
我的思路:01背包,如果以总和的一半的容量来放这些数字,最多正好能放总和的一半,则可以划分成两部分
我的代码:
class Solution { public: bool canPartition(vector<int>& nums) { int vol = 0; for (int i = 0; i < nums.size(); i++) vol += nums[i]; if (vol%2) return 0; vector<int> dp(vol/2+1); for (int i = 0; i < nums.size(); i++) { for (int v = vol/2; v >= nums[i]; v--) { dp[v] = max(dp[v], dp[v-nums[i]]+nums[i]); } } return dp[vol/2] == vol/2; } };
九章最优解:思路一样,有个抑或操作不是很明白
class Solution { public: bool canPartition(vector<int>& nums) { int len = nums.size(); int sum = 0; for(int i=0; i< len ; i++){ sum += nums[i]; } if(sum % 2 == 1 ){ return false; } sum /= 2; int * dp = new int[20000]; for(int i=0; i <=sum; i++) dp[i] = 0; dp[0] = 1; for(int i=0; i < len; i++){ for(int j = sum;j >= nums[i]; j--){ dp[j] |= dp[j - nums[i]]; } } return dp[sum]; } };
solution解法:擦嘞
class Solution { public: bool canPartition(vector<int>& nums) { bitset<10001> bits(1); int sum = accumulate(nums.begin(),nums.end(),0); for(auto n:nums) bits |= bits<<n; return !(sum&1)&&bits[sum>>1]; } };
474. Ones and Zeroes
题意:给定一组01串,问m个0、n个1最多能组成其中多少个
我的思路:二维背包
我的代码:
class Solution { public: int num0(string s) { int ans = 0; for (int i = 0; i < s.size(); i++) if (s[i] == '0') ans++; return ans; } int findMaxForm(vector<string>& strs, int m, int n) { vectorint> > dp(m+1, vector<int>(n+1, 0)); for (int i = 0; i < strs.size(); i++) { int cnt0 = num0(strs[i]), l = strs[i].size(); for (int j = m; j >= cnt0; j--) for (int k = n; k >= l-cnt0; k--) dp[j][k] = max(dp[j][k], dp[j-cnt0][k+cnt0-l]+1); } return dp[m][n]; } };
九章最优解:一样
solution解法:
class Solution { public: int findMaxForm(vector<string>& strs, int m, int n) { vectorint, int>> nums(strs.size(), pair<int, int>{}); for (int i = 0; i < strs.size(); ++i) nums[i] = count(strs[i]); sort(nums.begin(), nums.end(), [](const pair<int, int>& a, const pair<int, int>& b){ return a.first < b.first || (a.first == b.first && a.second < b.second); }); int result = 0; for (int i = 0; i < nums.size(); i++) { result = max(result, helper(nums, m, n, i)); } return result; } int helper(vector int, int>>& nums, int m, int n, int start) { int cnt = 0; for (int i = start; i < nums.size(); i++) { if (nums[i].first <= m && nums[i].second <= n) { cnt++; m = m - nums[i].first; n = n - nums[i].second; } } return cnt; } pair<int, int> count(string& s){ int ones = 0, zeros = 0; for (char& c : s){ if (c == '0') ++zeros; else ++ones; } return {zeros, ones}; } };
486. Predict the Winner
题意:给定一个数组,甲乙二人可以分别从首或者尾取一个数字,返回甲取得数字总和能否大于等于乙
我的思路:如果一方选择了两端的任意一个数,可以看成加,而另一方选择它的数对于自己来说可以看成是减。只要最后的结果不小于0,说明自己就比对手高。
我的代码:
class Solution { public: int dp(int i, int j, vector<int>& nums, int flag) { if (i == j) return nums[i]; if (flag) return max(dp(i+1, j, nums, flag^1)+nums[i], dp(i, j-1, nums, flag^1)+nums[j]); else return min(dp(i+1, j, nums, flag^1)-nums[i], dp(i, j-1, nums, flag^1)-nums[j]); } bool PredictTheWinner(vector<int>& nums) { return dp(0, nums.size()-1, nums, 1) >= 0; } };
solution解法:减少了很多重复工作
class Solution { public: int dp[30][30]; int f(int l, int r, vector<int>& nums) { if (l == r) return nums[l]; if (dp[l][r] != 0) return dp[l][r]; dp[l][r] = max(nums[l] - f(l + 1, r, nums), nums[r] - f(l, r - 1, nums)); return dp[l][r]; } bool PredictTheWinner(vector<int>& nums) { memset(dp, 0, sizeof(dp)); for (int i = 0; i < nums.size(); ++i) dp[i][i] = nums[i]; return f(0, nums.size() - 1, nums) >= 0; } };
494. Target Sum
题意:给定一个数组,可以在每个元素前乘+-1,求使得和为S的方案数
我的思路:暴搜所有情况
我的代码:
class Solution { public: int ans; void dfs(vector<int>& nums, int i, int sum, int S) { if (i == nums.size()) { if (sum == S) ans++; return; } dfs(nums, i+1, sum+nums[i], S); dfs(nums, i+1, sum-nums[i], S); } int findTargetSumWays(vector<int>& nums, int S) { dfs(nums, 0, 0, S); return ans; } };
solution解法:
1)暴力,如上
2)记忆化搜索
public class Solution { int count = 0; public int findTargetSumWays(int[] nums, int S) { int[][] memo = new int[nums.length][2001]; for (int[] row: memo) Arrays.fill(row, Integer.MIN_VALUE); return calculate(nums, 0, 0, S, memo); } public int calculate(int[] nums, int i, int sum, int S, int[][] memo) { if (i == nums.length) { if (sum == S) return 1; else return 0; } else { if (memo[i][sum + 1000] != Integer.MIN_VALUE) { return memo[i][sum + 1000]; } int add = calculate(nums, i + 1, sum + nums[i], S, memo); int subtract = calculate(nums, i + 1, sum - nums[i], S, memo); memo[i][sum + 1000] = add + subtract; return memo[i][sum + 1000]; } } }
3)二维dp
public class Solution { public int findTargetSumWays(int[] nums, int S) { int[][] dp = new int[nums.length][2001]; dp[0][nums[0] + 1000] = 1; dp[0][-nums[0] + 1000] += 1; for (int i = 1; i < nums.length; i++) { for (int sum = -1000; sum <= 1000; sum++) { if (dp[i - 1][sum + 1000] > 0) { dp[i][sum + nums[i] + 1000] += dp[i - 1][sum + 1000]; dp[i][sum - nums[i] + 1000] += dp[i - 1][sum + 1000]; } } } return S > 1000 ? 0 : dp[nums.length - 1][S + 1000]; } }
4)二维缩减到1维,类似于背包那样
public class Solution { public int findTargetSumWays(int[] nums, int S) { int[] dp = new int[2001]; dp[nums[0] + 1000] = 1; dp[-nums[0] + 1000] += 1; for (int i = 1; i < nums.length; i++) { int[] next = new int[2001]; for (int sum = -1000; sum <= 1000; sum++) { if (dp[sum + 1000] > 0) { next[sum + nums[i] + 1000] += dp[sum + 1000]; next[sum - nums[i] + 1000] += dp[sum + 1000]; } } dp = next; } return S > 1000 ? 0 : dp[S + 1000]; } }
514. Freedom Trail
题意:转转轮拼出单词,至少需要转多少次,允许有重复字符
我的思路:dp,状态转移方程:
dp[k][i] = min(dp[k][i], dp[k - 1][j] + min(abs(i - j), len(ring) - abs(i - j))),其中k表示当前字符在key中的下标,i表示当前字符在ring中的下标,j表示上一个字符在ring中的下标。
代码:
class Solution { public: int dfs(string r, string key, int ri) { if (key.length() == 0) return 0; int ans = 0x7fffffff; for (int i = 0; i < r.length(); i++) { if (r[(ri+i)%r.length()] == key[0]) ans = min(ans, min(i, (int)r.length()-i)+1+dfs(r, key.substr(1, key.length()-1), (ri+i)%r.length())); } return ans; } int findRotateSteps(string ring, string key) { int m = ring.length(), n = key.length(); vectorint>> dp(n+1, vector<int>(m)); for (int i = n-1; i >= 0; i--) for (int j = 0; j < m; j++) { dp[i][j] = 0x7fffffff; for (int k = 0; k < m; k++) if (ring[k] == key[i]) { int diff = abs(j-k); int step = min(diff,m-diff); dp[i][j] = min(dp[i][j], step + dp[i + 1][k]); } } return dp[0][0]+n; } };
516. Longest Palindromic Subsequence
题意:返回最长回文子串长度
我的思路:dp,状态转移方程
if (s[j] == s[i+j]) dp[j][j+i] = max(dp[j][j+i], dp[j+1][j+i-1]+2);
else dp[j][j+i] = max(dp[j][j+i], dp[j+1][j+i-1]);
我的代码:
class Solution { public: int longestPalindromeSubseq(string s) { int n = s.size(); if (n <= 1) return n; vectorint>> dp(n, vector<int>(n, 0)); for (int i = 0; i < n; i++) for (int j = 0; j+i < n; j++) { if (i == 0) dp[j][j+i] = 1; else if (i == 1) dp[j][j+i] = (s[j] == s[j+i])+1; else { dp[j][i+j] = max(dp[j+1][j+i], dp[j][j+i-1]); if (s[j] == s[i+j]) dp[j][j+i] = max(dp[j][j+i], dp[j+1][j+i-1]+2); else dp[j][j+i] = max(dp[j][j+i], dp[j+1][j+i-1]); } } return dp[0][n-1]; } };
solution解法:
int longestPalindromeSubseq(string s) { if (s.size() == 0) return 0; vector<int> dp(s.size(), 0); for (int i = s.size() - 1; i >=0; i--) { int prev = 1; for (int j = i + 1; j < s.size(); j++) { int curr; if (s[i] == s[j]) curr = 2 + dp[j - 1]; else curr = max(prev, dp[j]); dp[j - 1] = prev; prev = curr; } dp[s.size() - 1] = prev; } return dp[s.size() -1]; }
552. Student Attendance Record II
题意:求生成长度为n的一个字符串总共有多少种方法 ,要求:P无限放,A最多放1个,连续的L最多有两个
我的思路:看的disscussion的解法,非常好,后做了一个空间上的优化
class Solution { public: int checkRecord(int n) { int MOD = 1000000007; vectorint> > > f (2, vector int> >(2, vector<int>(3))); f[0] = {{1, 1, 1}, {1, 1, 1}}; for (int i = 1; i <= n; i++) for (int j = 0; j < 2; j++) for (int k = 0; k < 3; k++) { int val = f[(i-1)%2][j][2]; // ...任何情况下都可以放P if (j > 0) val = (val + f[(i-1)%2][j - 1][2]) % MOD; // ...i-1个没有A的时候可以放A if (k > 0) val = (val + f[(i-1)%2][j][k - 1]) % MOD; // ...最多k-1个L的时候可以放L f[i%2][j][k] = val; } return f[n%2][1][2]; } };
583. Delete Operation for Two Strings
题意:两个字符串经过多少次删除操作可以变成一样的
我的思路:lcs
我的代码:
class Solution { public: int minDistance(string word1, string word2) { int m = word1.size(), n = word2.size(); vectorint> > dp(m+1, vector<int>(n+1)); dp[0][0] = 0; for (int i = 1; i <= m; i++) for (int j = 1; j <= n; j++) { if (word1[i-1] == word2[j-1]) dp[i][j] = dp[i-1][j-1]+1; else dp[i][j] = max(dp[i-1][j], dp[i][j-1]); } return m+n-2*dp[m][n]; } };
623. Add One Row to Tree
题意:在树的某一层加一层某值
我的思路:常规树dfs
我的代码:
class Solution { public: void dfs(TreeNode* root, int v, int d, int i) { if (i == d-1) { TreeNode* tmpl = new TreeNode(v); tmpl->left = root->left; root->left = tmpl; TreeNode* tmpr = new TreeNode(v); tmpr->right = root->right; root->right = tmpr; } else if (i < d-1) { if (root->left) dfs(root->left, v, d, i+1); if (root->right) dfs(root->right, v, d, i+1); } } TreeNode* addOneRow(TreeNode* root, int v, int d) { if (d == 1) { TreeNode* tmp = new TreeNode(v); tmp->left = root; return tmp; } if (root) dfs(root, v, d, 1); return root; } };
646. Maximum Length of Pair Chain
题意:给定一组区间,求最长的区间链(前一个区间尾小于后一个区间头)
我的思路:LCS模板题
我的代码:没用logn优化
class Solution { public: static bool cmp(const vector<int> &a, const vector<int> &b) { return a[0] == b[0] ? a[1]1] : a[0]0]; } int findLongestChain(vectorint>>& pairs) { if (pairs.size() <= 1) return pairs.size(); vector<int> dp(pairs.size(), 1); int ans = 0; sort(pairs.begin(), pairs.end(), cmp); for (int i = 1; i < pairs.size(); i++) { for (int j = 0; j < i; j++) { if (pairs[j][1] < pairs[i][0]) dp[i] = max(dp[i], dp[j]+1); } ans = max(ans, dp[i]); } return ans; } };
solution解法:
bool comp(pair<int, int>a, pair<int, int>b) { return a.second < b.second; } class Solution { public: int findLongestChain(vectorint>>& pairs) { vector int, int>> v; for (int i = 0; i < pairs.size(); ++i) { v.push_back(make_pair(pairs[i][0], pairs[i][1])); } sort(v.begin(), v.end(), comp); for (int i = 0; i < pairs.size(); ++i) { pairs[i][0] = v[i].first; pairs[i][1] = v[i].second; } int a = 1; pair<int, int> p = v[0]; for (int i = 1; i < v.size(); ++i) { if (v[i].first > p.second) { a++; p = v[i]; } } return a; } };
756. Pyramid Transition Matrix
题意:给定最底层和所有两个字母之上可以放置的模式,问能否构成金字塔
思路: https://segmentfault.com/a/1190000012727144
我的代码:
class Solution { public: bool pyramidTransition(string bottom, vector<string>& allowed) { int n = bottom.length(); unordered_map<string, vector<char>> mp; vectorset<char>>> dp(n, vector<set<char>>(n)); for (int i = 0; i < allowed.size(); i++) mp[allowed[i].substr(0, 2)].push_back(allowed[i][2]); for (int i = 0; i < n; i++) dp[0][i].insert(bottom[i]); for (int i = 1; i < n; i++) for (int j = 0; j < n-i; j++) for (char a: dp[i-1][j]) for (char b: dp[i-1][j+1]) { string s; s = s+a+b; for (char c: mp[s]) dp[i][j].insert(c); } return !dp[n-1][0].empty(); } };