209.长度最小的子数组
题目链接:https://leetcode.cn/problems/minimum-size-subarray-sum/
视频讲解:https://www.bilibili.com/video/BV1tZ4y1q7XE
我的解题思路
1暴力解法(还是不符合题目要求的时间复杂度,但是很暴力)
int minSubArrayLen(int target, int* nums, int numsSize){
int minLength = INT_MAX;
int sum;
int left, right;
for(left = 0; left < numsSize; ++left) {
sum = 0;
for(right = left; right < numsSize; ++right) {
sum += nums[right];
if(sum >= target) {
int subLength = right - left + 1;
minLength = minLength < subLength ? minLength : subLength;
}
}
}
return minLength == INT_MAX ? 0 : minLength;
}
int minSubArrayLen(int target, int* nums, int numsSize) {
int minLength = INT_MAX;
int sum = 0;
int left = 0;
for (int right = 0; right < numsSize; ++right) {
sum += nums[right];
while (sum >= target) {
int subLength = right - left + 1;
minLength = (minLength < subLength) ? minLength : subLength;
sum -= nums[left++];
}
}
return (minLength == INT_MAX) ? 0 : minLength;
}
学习反思
昨天的题目其实有两个都用到了双指针法,今天能更快的想到,但是今天的双指针法和昨天的还不太一样,又被称为滑动窗口
滑动窗口
所谓滑动窗口,就是不断的调节子序列的起始位置和终止位置,从而得出我们要想的结果。
在暴力解法中,是一个for循环滑动窗口的起始位置,一个for循环为滑动窗口的终止位置,用两个for循环 完成了一个不断搜索区间的过程。
那么滑动窗口如何用一个for循环来完成这个操作呢。
首先要思考 如果用一个for循环,那么应该表示 滑动窗口的起始位置,还是终止位置。
如果只用一个for循环来表示 滑动窗口的起始位置,那么如何遍历剩下的终止位置?
此时难免再次陷入 暴力解法的怪圈。
所以 只用一个for循环,那么这个循环的索引,一定是表示 滑动窗口的终止位置。
在本题中实现滑动窗口,主要确定如下三点:
- 窗口内是什么?
- 如何移动窗口的起始位置?
- 如何移动窗口的结束位置?
窗口就是 满足其和 ≥ s 的长度最小的 连续 子数组。
窗口的起始位置如何移动:如果当前窗口的值大于等于s了,窗口就要向前移动了(也就是该缩小了)。
窗口的结束位置如何移动:窗口的结束位置就是遍历数组的指针,也就是for循环里的索引。
可以发现滑动窗口的精妙之处在于根据当前子序列和大小的情况,不断调节子序列的起始位置。从而将O(n^2)暴力解法降为O(n)。
59.螺旋矩阵II
我的解题思路
模拟顺时针画矩阵的过程,可以把方阵的每一圈4个顶点:(i, i)、(i, n-i-1)、(n-i-1, n-i-1)、(n-i-1, i)
以某个顶点为起始点, 下一个为结束点, 且为左开右闭即可
int** generateMatrix(int n, int* returnSize, int** returnColumnSizes){
*returnSize = n;
*returnColumnSizes = (int*)malloc(sizeof(int) * n);
int** ans = (int**)malloc(sizeof(int*) * n);
int i;
for(i = 0; i < n; i++) {
ans[i] = (int*)malloc(sizeof(int) * n);
(*returnColumnSizes)[i] = n;
}
int startX = 0;
int startY = 0;
int mid = n / 2;
int loop = n / 2;
int offset = 1;
int count = 1;
while(loop) {
int i = startX;
int j = startY;
for(; j < startY + n - offset; j++) {
ans[startX][j] = count++;
}
for(; i < startX + n - offset; i++) {
ans[i][j] = count++;
}
for(; j > startY; j--) {
ans[i][j] = count++;
}
for(; i > startX; i--) {
ans[i][j] = count++;
}
offset+=2;
startX++;
startY++;
loop--;
}
if(n%2)
ans[mid][mid] = count;
return ans;
}
学习反思
这个题目可能本身不是很难,就是很麻烦要考虑很多东西,比如奇偶不一样可能会导致中心格能不能填上一类的。
总结
对滑动窗口有了更深刻的印象,同时有了昨天的基础,写博客的速度也快了不少,加油!!!