209.长度最小的子数组https://leetcode.cn/problems/minimum-size-subarray-sum/: 给定一个含有n
个正整数的数组和一个正整数target
。找出该数组中满足其总和大于等于target
的长度最小的子数组[nums_l, nums_{l+1}, ..., nums_{r-1}, nums_r]
,并返回其长度。如果不存在符合条件的子数组,返回0
。
(1)暴力求解法:利用两个循环,分别遍历子列的起始位置和终止位置;若检查到和>= target
的子列,将其长度记为len;实时更新满足条件的最短子列长result。
class Solution {
public:int minSubArrayLen(int target, vector<int>& nums) {int sum = 0, len = 0, s = nums.size()+10;for (int i = 0; i < nums.size(); i++){sum = 0;for (int j = i; j <nums.size(); j++){sum += nums[j];if (sum >= target) {len = j-i+1;break; }else len = nums.size()+10;}if (s > len) s = len;}return s == nums.size() + 10 ? 0 : s;}
};
时间复杂度:O(n^2)
,这导致当n
很大时超出时间限制;
空间复杂度:O(1)
。
(2)移动窗口解法:利用一个for循环遍历窗口终止位置,以其和sum
是否大于target
作为元素是否在窗口中的依据。若sum
小于target
,向后移动窗口终止位置;若sum
大于target
,向后移动窗口起始位置。注意移动时和sum
的变化;并实时记录和比较子列长度。
class Solution {
public:int minSubArrayLen(int target, vector<int>& nums) {int sum = 0, sublenth = 0, result = INT32_MAX;int i = 0; //star indexfor (int j = 0; j < nums.size(); j++){sum += nums[j];while(sum >= target){sublenth = j - i + 1;result = result < sublenth ? result : sublenth;sum -= nums[i++]; // 这里体现出滑动窗口的精髓之处,不断变更icontinue;}}return result == INT32_MAX ? 0 : result;}
};
空间复杂度:O(n)
;
时间复杂度:O(1)
。
(3)解题困难:①不能准确判断移动窗口的起始位置i和终止位置j的设置;②尝试先固定子数组长度,再找满足和条件的子数组,最终还是要用两个循环。
59.螺旋矩阵https://leetcode.cn/problems/spiral-matrix-ii/: 给你一个正整数n
,生成一个包含1
到n^2
所有元素,且元素按顺时针顺序螺旋排列的n x n
正方形矩阵matrix
。
(1)自我思路:n
为奇数时有中心,为偶数时只有外圈;一圈四边,每边的元素数目只计算左闭右开区间内的元素。
(2)循环求解:
class Solution {
public:vector<vector<int>> generateMatrix(int n) {std::vector<std::vector<int>> arr(n, std::vector<int>(n,0));int loop = n / 2; //记录要填充圈数,n为奇数时还需要单独处理中间位置int startx = 0, starty = 0; // 定义每循环一个圈的起始位置int mid = n/2;//记录中间位置int offset = 1;int count = 1;int i, j;while (loop--){i = startx; j = starty;for (j; j < n - offset; j++){ //j从0变到n-offset,n-offset未进入循环arr[i][j] = count++;}for (i; i < n - offset; i++) {//j从0变到n-1arr[i][j] = count++;}for (; j > startx; j--){ //j从n-offset 变到startxrr[i][j] = count++;}for (; i > starty; i--){ //i从n-offset 变到startyarr[i][j] = count++;}// 第二圈开始的时候,起始位置要各自加1startx++;starty++;// offset 控制每一圈里每一条边遍历的长度offset += 1;}if (n % 2) arr[mid][mid] = n*n;return arr;}
};
时间复杂度:O(n^2)
;
空间复杂度:O(1)
。
(3)主要困难:误用行列乘积给元素赋值;区间端点i与j的设置;
(4)收获:自增运算符有共同效果和细微区别。① 后缀自增:i++ 会先返回 i 的当前值,然后 i 的值增加1。② 前缀自增:++i 会先将 i 的值增加1,然后返回 i 的新值。例如
int i = 1;
int a = i++; // a = 1, i = 2
int b = ++i; // i = 3, b = 3