代码随想录算法训练营第2天 | 209.长度最小的子数组、59.螺旋矩阵Ⅱ
209.长度最小的子数组
解题思路
- 暴力解法
两个 for 循环寻找符合条件的子数组
- 滑动窗口
滑动窗口就是不断地调节子数组的起始位置和终止位置,从而得到想要的结果。
定义两个指针 i 和 j ,其中 i 指向滑动窗口的起始位置,j 指向窗口的终止位置,定义 sum 记录窗口中元素值总和,循环开始后,j 指针开始向前移动,此时 sum 实时记录窗口中总和,一旦 sum>=target,此时开始更新子数组的最小长度,j 指针保持不动,i 指针开始右移,同时将 nums[i] 值从 sum 中减去,直到 sum<target ,此时得到子数组的最小长度 subLength = j-i+1 。
代码实现
暴力解法
class Solution {
public:
int minSubArrayLen(int target, vector<int>& nums) {
int sum = 0;
int subLength = 0;
int result = INT_MAX;
for (int i = 0; i < nums.size(); i++) {
sum = 0;
for (int j = i; j < nums.size(); j++) {
sum += nums[j];
if (sum >= target) {
subLength = j - i + 1;
result = result < subLength ? result : subLength;
break;
}
}
}
return result == INT_MAX ? 0 : result;
}
};
滑动窗口
class Solution {
public:
int minSubArrayLen(int target, vector<int>& nums) {
int result = INT_MAX;
int i = 0;
int sum = 0;
int subLength = 0;
for (int j = 0; j < nums.size(); j++) {
sum += nums[j];
while (sum >= target) {
subLength = j - i + 1;
result = result < subLength ? result : subLength;
sum -= nums[i++];
}
}
return result == INT_MAX ? 0 : result;
}
};
题目总结
滑动窗口的关键在于:何时扩大窗口和何时缩小窗口,根据当前子数组和的大小,不断调节子数组的起始位置。
59.螺旋矩阵Ⅱ
解题思路
按照右、下、左、上的顺序遍历数组,坚持循环不变量的原则。矩阵的四条边坚持一致的左闭右开或左开右闭的原则,贴一张卡哥的图。
代码实现
class Solution {
public:
vector<vector<int>> generateMatrix(int n) {
vector<vector<int>> res(n, vector<int>(n, 0));
int startx = 0, starty = 0; // 每圈起始位置
int loop = n / 2; // 循环圈数
int count = 1; // 记录数值
int offset = 1; // 去更向内的一圈,在结束一圈后,起始位置向后移,结束位置向前移
int i, j;
int mid = n / 2;
while (loop--) {
for (j = starty; j < n - offset; j++) {
res[startx][j] = count++;
}
for (i = startx; i < n - offset; i++) {
res[i][j] = count++;
}
for (; j > starty; j--) {
res[i][j] = count++;
}
for (; i > startx; i--) {
res[i][j] = count++;
}
startx++;
starty++;
offset += 1;
}
if (n % 2) // n为奇数,单独给最中间的数赋值
{
res[mid][mid] = count;
}
return res;
}
};
题目总结
顺时针画矩阵顺序:
- 从左到右填充上行
- 从上到下填充右行
- 从右到左填充下行
- 从下到上填充左行
从外向内一圈一圈画,注意区间开闭情况。