【滑动窗口:209 长度最小子数组 904.水果成篮 76.最小覆盖子串
1658 最少操作x变0】
難點可能在如何判斷和存儲狀態(可能用到複雜的數據結構)76,還可能在把題目轉換成基本款 1658
【螺旋矩阵: 59.螺旋矩阵ii 54.螺旋矩阵=剑指29.顺时针打印矩阵,885.螺旋矩阵iii 】
難點在大於等於,大於,小於等於,小於的選擇。如果不處理特殊情況,就是[start, end] [start+1,end] [end-1,start] [end-1][start-1];如果處理特殊情況就是[start,end-1][start,end-1][end-1,start] [end-1,start]
長方形的比正方形的難,正方形的特殊情況只是剩最後一個
方向很多比如四个方向都有的时候,最好提前弄一个vector{0,1,0,-1} 之类的(棋盘格都是这么做的)选择方向的时候直接用不容易错
代码随想录算法训练营第2天 | 977.有序数组的平方 ,209.长度最小的子数组 ,59.螺旋矩阵II ,总结_weixin_51674457的博客-CSDN博客
只有209和59是二刷,都過了
209长度最小子数组
sum要达到target,自己滑动窗口法ac,不断往前囊括新的一个,然后试着从头减少一个个,看sum还够不够
mycode:
int minSubArrayLen(int target, vector<int>& nums) {
int minlen=200000;
int sum=0;
int fast=0;
int slow=0;
while(fast<nums.size()){
sum+=nums[fast];
while(sum-nums[slow]>=target && slow<=fast){
sum-=nums[slow];
slow++;
}
if(sum>=target) minlen=min(minlen,fast-slow+1);
fast++;
}
return minlen==200000?0:minlen;
}
逻辑整理的更简洁:
int minSubArrayLen(int target, vector<int>& nums) {
int minlen=200000;
int sum=0;
int fast=0;
int slow=0;
while(fast<nums.size()){
sum+=nums[fast];
while(sum>=target){
minlen=min(minlen,fast-slow+1);
sum-=nums[slow++];
}
fast++;
}
return minlen==200000?0:minlen;
}
904 水果成篮
一刷,快写出来但没写出来。数据结构unordered map选对了,我的问题出在前面的要一个一个减去,不能一下子把前面某个直接设为0,从map里删掉,那样会混乱。比如 1 2 1 1 2 3,遇到3了我们需要把map里的1清除掉,我们要连续着模拟:不要1,不要2,不要1,不要1,因为不可能只是不要所有的1,但2还留下的。
int totalFruit(vector<int>& vec) {
unordered_map<int, int> count;
int start = 0;
int res = 0;
for (int end = 0; end < vec.size(); end++) {
count[vec[end]]++;
while (count.size() > 2) {
count[vec[start]]--;
if (count[vec[start]] == 0) {
count.erase(vec[start]);
}
start++;
}
res = max(res, end - start + 1);
}
return res;
}
另外关于++a,和a++,如果不涉及return,返回值,或者赋值,就用任意都一样都可以
++a是先+再返回值
76 最小覆盖子串 hard
一刷。没做出来。难点在于 判断方法变得复杂,用了unordered_map<char, int>
string minWindow(string s, string t) {
if (s.size() < t.size()) return "";
//create a counter for t
unordered_map<char, int> dict_t;
for (char c : t) dict_t[c]++;
unordered_map<char, int> window;
int left = 0, right = 0;
int formed = 0;
int required = dict_t.size();
// Save the minimum length and starting index of the result
int min_length = INT_MAX, start = 0;
while (right < s.size()) {
char c = s[right];
window[c]++;
if (window[c] == dict_t[c]) {
formed++;
}
while (left <= right && formed == required) {
c = s[left];
// end is right, start os left
if (right - left + 1 < min_length) {
min_length = right - left + 1;
start = left;
}
window[c]--;
if (window[c] < dict_t[c]) {
formed--;
}
left++;
}
right++;
}
return min_length == INT_MAX ? "" : s.substr(start, min_length);
}
1658. Minimum Operations to Reduce X to Zero
1658 最少操作x变0
变体 不要求两头,改为求中间subary 和為target,記得原來求min 現在求max長度
和209沒差
int minOperations(vector<int>& nums, int x) {
int start=0; int end=0;
int res=-1;
int sum=0;
int target=accumulate(nums.begin(),nums.end(),0);
target-=x;
if(target<0) return -1;
while(end<nums.size()){
sum+=nums[end++];
while(sum>target) sum-=nums[start++];
if(sum==target) res=max(res,end-start);
}
return res==-1? -1:nums.size()-res;
}
【螺旋矩阵: 59.螺旋矩阵ii 54.螺旋矩阵 剑指29.顺时针打印矩阵 】
59.螺旋矩阵ii
二刷很快,關鍵是螺旋走下來 每行/列 留下最後一個
vector<vector<int>> generateMatrix(int n) {
int cnt=1;
vector<vector<int>> res(n, vector<int>(n, 0));
int start=0;
int end=n-1;
while(start<end){
for(int i=start;i<end;i++) res[start][i]=cnt++;
for(int i=start;i<end;i++) res[i][end]=cnt++;
for(int i=end;i>start;i--) res[end][i]=cnt++;
for(int i=end;i>start;i--) res[i][start]=cnt++;
start++;
end--;
}
if(start==end) res[start][start]=cnt;
return res;
}
還有一种不處理特殊情況的寫法,感覺更好:
vector<vector<int>> generateMatrix(int n) {
int cnt = 1;
vector<vector<int>> res(n, vector<int>(n, 0));
int start = 0;
int end = n - 1;
while (start <= end) {
for (int i = start; i <= end; i++) res[start][i] = cnt++;
for (int i = start + 1; i <= end; i++) res[i][end] = cnt++;
for (int i = end - 1; i >= start; i--) res[end][i] = cnt++;
for (int i = end - 1; i > start; i--) res[i][start] = cnt++;
start++;
end--;
}
return res;
}
54.螺旋矩阵
和剑指29.顺时针打印矩阵 一樣的
59是放入,54是輸出,但54不一定是正方形了,可能是長方形或者一行/一列
自己做了很久還是問了gpt,因爲特殊情況處理不好:
這是不處理特殊情況的寫法:
vector<int> spiralOrder(vector<vector<int>>& matrix) {
vector<int> res;
int n = matrix.size();
int m = matrix[0].size();
int start1 = 0;
int start2 = 0;
int end1 = n - 1;
int end2 = m - 1;
while (start1 <= end1 && start2 <= end2) {
for (int i = start2; i <= end2; i++) {
res.push_back(matrix[start1][i]);
}
for (int i = start1 + 1; i <= end1; i++) {
res.push_back(matrix[i][end2]);
}
if (start1 < end1) {
for (int i = end2 - 1; i >= start2; i--) {
res.push_back(matrix[end1][i]);
}
}
if (start2 < end2) {
for (int i = end1 - 1; i > start1; i--) {
res.push_back(matrix[i][start2]);
}
}
start1++;
start2++;
end1--;
end2--;
}
return res;
}
這是處理特殊情況的寫法:
vector<int> spiralOrder(vector<vector<int>>& matrix) {
vector<int> res;
int n = matrix.size();
int m = matrix[0].size();
int start1 = 0;
int start2 = 0;
int end1 = n - 1;
int end2 = m - 1;
while (start1 < end1 && start2 < end2) {
for (int i = start2; i < end2; i++) {
res.push_back(matrix[start1][i]);
}
for (int i = start1; i < end1; i++) {
res.push_back(matrix[i][end2]);
}
for (int i = end2; i > start2; i--) {
res.push_back(matrix[end1][i]);
}
for (int i = end1; i > start1; i--) {
res.push_back(matrix[i][start2]);
}
start1++;
start2++;
end1--;
end2--;
}
// // 处理剩下的元素
if (start1 == end1) { // 如果还剩一行
for (int i = start2; i <= end2; i++) {
res.push_back(matrix[start1][i]);
}
}
else if (start2 == end2) { // 如果还剩一列
for (int i = start1; i <= end1; i++) {
res.push_back(matrix[i][start2]);
}
}
return res;
}
885 螺旋矩阵iii
思路没错,但是自己写了很久结果也不对,可能是自己的实现方式太乱了,容易出bug
问了gpt给的代码不错:
vector<vector<int>> spiralMatrixIII(int rows, int cols, int rStart, int cStart) {
vector<vector<int>> res;
int dx[] = {0, 1, 0, -1};
int dy[] = {1, 0, -1, 0};
int x = rStart, y = cStart;
int n = rows * cols;
res.push_back({x, y});
int step = 0;
while (res.size() < n) {
for (int i = 0; i < 4; i++) { // 按照右下左上的顺序遍历
if (i % 2 == 0) step++; // 每完成一个右或左方向,增加步长
for (int j = 0; j < step; j++) {
x += dx[i];
y += dy[i];
if (x >= 0 && x < rows && y >= 0 && y < cols) {
res.push_back({x, y});
}
}
}
}
return res;
}