算法训练营 第二天
977. 有序数组的平方
这道题的关键在于要用时间复杂度为O(n)的算法做题,也就是只遍历一遍nums数组就能排序好,因此想到用双指针的方法,数组的两端设置指针,依次填入新数组。
209 长度最小的子数组
这道题是滑动窗口题,关键在于想好怎么设置循环,窗口前端先动,前端到达数组尾端则停止循环,因此将fast指针作为循环设置条件,for(;fast!=nums.size();fast++)
想清楚这个条件了之后,再写里面的语句就会容易很多。
我的代码是这样的
class Solution {
public:
int minSubArrayLen(int target, vector<int>& nums) {
int slow = 0, fast = 1;
int size=1e5+1;
int sum = nums[0];
if (sum >= target)
return 1;
for (;fast!=nums.size();fast++) {
sum += nums[fast];
if (sum < target) {
continue;
}
while (sum - nums[slow] >= target) {
sum -= nums[slow++];
}
if (size > fast - slow+1)
size = fast - slow+1;
}
if (size == 1e5 + 1)
return 0;
return size;
}
};
代码随想录的代码
class Solution {
public:
int minSubArrayLen(int s, vector<int>& nums) {
int result = INT32_MAX;
int sum = 0; // 滑动窗口数值之和
int i = 0; // 滑动窗口起始位置
int subLength = 0; // 滑动窗口的长度
for (int j = 0; j < nums.size(); j++) {
sum += nums[j];
// 注意这里使用while,每次更新 i(起始位置),并不断比较子序列是否符合条件
while (sum >= s) {
subLength = (j - i + 1); // 取子序列的长度
result = result < subLength ? result : subLength;
sum -= nums[i++]; // 这里体现出滑动窗口的精髓之处,不断变更i(子序列的起始位置)
}
}
// 如果result没有被赋值的话,就返回0,说明没有符合条件的子序列
return result == INT32_MAX ? 0 : result;
}
};
代码随想录更简略,但思路都相同,时间空间复杂度相同。
59.螺旋矩阵
这道题的重点是确定循环不变量,一个循环里要处理什么内容,一共几次循环,这道题是nxn的序列,如果是mxn的矩阵,又应该怎么写,思路是一样的,只是每次循环的startx和starty要重新斟酌赋值,最中间的那一圈要怎么赋值也得重新考虑。