day2 滑动窗口 | 螺旋数组

滑动窗口

首先复习滑动窗口的模板形式:

for(int i = 0; i < n; ++i) {
    while(check()) {
        // calculate len of i->j
        j++;
    }
}

关于时间复杂度,因为j是不回头的,最多从0->n 而i也是从0->n,所以时间复杂度是O(n+n) = O(n)
leetcode 209.长度最小的子数组
这题的check就是 只要满足

while(sum >= target) {
    len = min(len, i - j + 1);
    sum -= nums[j];
    j++;
}

我们就把 j 这个位置的元素删掉,看看还是不是满足长度要求,并且更新答案。

int minSubArrayLen(int target, vector<int>& nums) {
        int j = 0;
        int sum = 0;
        int len = INT_MAX;
        for(int i = 0; i < nums.size(); ++i) {
            sum += nums[i];
            while(sum >= target) {
                len = min(len, i - j + 1);
                sum -= nums[j];
                j++;
            }
        }
        return len == INT_MAX ? 0 : len;
    }

最后要注意的是我们并不一定能找到这样的数组,所以要特判一下。

螺旋数组Ⅱ

做这道题之前先完成螺旋数组Ⅰ
这道题我没有按照卡哥的方法写,虽然卡哥的方法也比较好理解,但是我似乎更能接受直接模拟的思路,走到哪个位置接下来应该怎么继续走,就类似于一个状态机,当前的状态是什么,接下来应该怎么走,走完之后带来的改变是什么,这样理解起来也比较顺利。
这道题难点在于处理边界和判断逻辑,我们不妨定义一个方向和一个坐标。每次只走一步,一步一步来,当前的方向和坐标是什么,如果要向上走,应该注意什么,诸如此类,我们定义一个上下左右边界为-1,n,-1,n,也就是数组刚开始越界的位置,如何按照当前的方向继续往下走就越界了,说明我们该掉头了,另外一点就是,我们走的这个螺旋路径是越来越小的,所以这个“边界”其实随着我们的路径在不断的缩小,没走完一横条或者一竖条,我们的上(下)边界或者右(左)边界就会改变。

class Solution {
public:
    enum direction {
        UP, DOWN, LEFT, RIGHT
    }dir;
    vector<vector<int>> generateMatrix(int n) {
        int idx = 1;
        vector<vector<int>> ans(n, vector<int>(n));
        int upBorder = -1;
        int leftBorder = -1;
        int rightBorder = n;
        int downBorder = n;
        int x = 0, y = 0;
        dir = RIGHT;
        while(true) {
            if(idx == n * n + 1) {
                break;
            }
            ans[y][x] = idx;
            switch(dir) {
                case UP:
                if(y - 1 == upBorder) {
                    dir = RIGHT;
                    x++;
                    leftBorder++;
                }
                else {
                    y--;
                }
                break;
                case DOWN:
                if(y + 1 == downBorder) {
                    dir = LEFT;
                    x--;
                    rightBorder--;
                }
                else {
                    y++;
                }
                break;
                case LEFT:
                if(x - 1 == leftBorder) {
                    y--;
                    dir = UP;
                    down_border--;
                }
                else {
                    x--;
                }
                break;
                case RIGHT:
                if(x + 1 == rightBorder) {
                    dir = DOWN;
                    y++;
                    upBorder++;
                }
                else {
                    x++;
                }
                break;
            }
            idx++;
        }
        return ans;
    }
};
posted @ 2023-12-28 17:02  ccnju  阅读(6)  评论(0)    收藏  举报