柱状图中的最大矩形
$l$数组存储第$i$个数左边第一个小于$i$高度的索引,$r$数组存储第$i$个数右边第一个小于$i$高度的索引;
class Solution { public: int largestRectangleArea(vector<int>& heights){ int n = heights.size(),ans = 0; int l[n],r[n]; l[0] = -1; r[n - 1] = n; for(int i = 1;i < n;i++){ if(heights[i] > heights[i - 1]){ l[i] = i - 1; }else{ int tag = l[i - 1]; while(tag >= 0 && heights[tag] >= heights[i]){ tag = l[tag]; } l[i] = tag; } } for(int i = n - 2;i >= 0;i--){ if(heights[i] > heights[i + 1]){ r[i] = i + 1; }else{ int tag = r[i + 1]; while(tag < n && heights[tag] >= heights[i]){ tag = r[tag]; } r[i] = tag; } } for(int i = 0;i < n;i++){ int s = (r[i] - l[i] - 1) * heights[i]; if(s > ans){ ans = s; } } return ans; } };
最大矩形
每层算累计高度然后调用上一问的接口得到结果;
class Solution { public: int largestRectangleArea(vector<int>& heights){ int n = heights.size(),ans = 0; int l[n],r[n]; l[0] = -1; r[n - 1] = n; for(int i = 1;i < n;i++){ if(heights[i] > heights[i - 1]){ l[i] = i - 1; }else{ int tag = l[i - 1]; while(tag >= 0 && heights[tag] >= heights[i]){ tag = l[tag]; } l[i] = tag; } } for(int i = n - 2;i >= 0;i--){ if(heights[i] > heights[i + 1]){ r[i] = i + 1; }else{ int tag = r[i + 1]; while(tag < n && heights[tag] >= heights[i]){ tag = r[tag]; } r[i] = tag; } } for(int i = 0;i < n;i++){ int s = (r[i] - l[i] - 1) * heights[i]; if(s > ans){ ans = s; } } return ans; } int maximalRectangle(vector<vector<char>>& matrix) { vector<int> heights; int m = matrix.size(),n = matrix[0].size(),ans = 0; for(int i = 0;i < n;i++){ if(matrix[0][i] == '1'){ heights.push_back(1); }else{ heights.push_back(0); } } ans = largestRectangleArea(heights); for(int i = 1;i < m;i++){ for(int j = 0;j < n;j++){ if(matrix[i][j] == '1'){ heights[j] = heights[j] + 1; }else{ heights[j] = 0; } } int s = largestRectangleArea(heights); if(s > ans){ ans = s; } } return ans; } };
最小覆盖子串
滑动窗口,遍历后记录满足条件的最小窗口;
class Solution { public: string minWindow(string s, string t) { int l = 0,r = 0,tip = t.size(); int ans1 = -1, ans2 = -1, ans = s.size(); int idx[2][26 * 2]; memset(idx, 0, sizeof(idx)); for(int i = 0; i < t.size(); i++){ if(t[i] >= 'A' && t[i] <= 'Z'){ idx[0][int(t[i]) - 65] = 1; idx[1][int(t[i]) - 65]++; }else{ idx[0][int(t[i]) - 81] = 1; idx[1][int(t[i]) - 81]++; } } for(r = 0; r < s.size(); r++){ if(s[r] >= 'A' && s[r] <= 'Z'){ if(idx[0][int(s[r]) - 65] == 1 && idx[1][int(s[r]) - 65] > 0){ tip--; } idx[1][int(s[r]) - 65]--; }else if(s[r] >= 'a' && s[r] <= 'z'){ if(idx[0][int(s[r]) - 81] == 1 && idx[1][int(s[r]) - 81] > 0){ tip--; } idx[1][int(s[r]) - 81]--; } while(tip == 0 && l <= r){ if(r - l < ans){ ans = r - l; ans1 = l; ans2 = r; } if(s[l] >= 'A' && s[l] <= 'Z'){ if(idx[0][int(s[l]) - 65] == 1 && idx[1][int(s[l]) - 65] == 0){ tip++; } idx[1][int(s[l]) - 65]++; }else if(s[l] >= 'a' && s[l] <= 'z'){ if(idx[0][int(s[l]) - 81] == 1 && idx[1][int(s[l]) - 81] == 0){ tip++; } idx[1][int(s[l]) - 81]++; } l++; if(l > r){ break; } } } if(ans1 == -1){ return ""; }else{ return s.substr(ans1, ans2 - ans1 + 1); } } };
最长连续序列
直接$sort$比$O(n)$还快,真的无语,思路就是用$unordered$_$set$去重顺便免于排序,然后遍历一遍计算最长连续序列;
class Solution { public: unordered_set<int> idx; int longestConsecutive(vector<int>& nums) { idx.clear(); int ans = 0; for(int i = 0;i < nums.size();i++){ idx.insert(nums[i]); } for(const int& num : idx){ if(!idx.count(num - 1)){ int now = 1, k = num; while(idx.count(k + 1)){ k++; now++; } ans = max(now, ans); } } return ans; } };
单词拆分
$ans[i]$表示以 i 结尾的字符能否被表示,每次先判断整体能否被表示,然后后向分词判断分别能否被表示;
class Solution { public: unordered_map<string, bool> idx; bool wordBreak(string s, vector<string>& wordDict) { for(int i = 0;i < wordDict.size();i++){ idx[wordDict[i]] = true; } vector<bool> ans(s.size(), false); for(int i = 0;i < s.size();i++){ if(idx.count(s.substr(0, i + 1)) != 0){ ans[i] = true; }else{ for(int j = i;j > 0;j--){ if(ans[j - 1] && idx.count(s.substr(j, i - j + 1)) != 0){ ans[i] = true; break; } } } } return ans[s.size() - 1]; } };