代码随想录算法训练营19期第2天| 滑动窗口,螺旋矩阵模拟 (二刷)

【滑动窗口: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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值