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;
}
};

浙公网安备 33010602011771号