算法训练记录——Day02
前言
这几天都在外面,上一篇博客还是在网吧写的,真是绝了哈哈哈哈哈哈,回来了就要跟上进度,不能被拉下太多了,冲冲冲!!!
977.有序数组的平方
已经很久没有感受到写一次代码就Ac的感觉了,果然爽(简单题我重拳出击)。
思路: 非递减排序整数数组有正有负,那么平方一定是两边大,中间最小。用双指针法,头尾对比后加入新队列即可。
int len = nums.size();
int left = 0, right = len - 1;
vector<int> res(0, len);
while(left <= right) {
if (nums[left] * nums[left] <= nums[right] * nums[right]) {
res[--len] = nums[right] * nums[right--];
} else
res[--len] = nums[left] * nums[left++];
}
return res;
209.长度最小的子数组
这题是中等题,给自己的时间是20min,没有思路就看题解。(实际耗时45min)
思路:维护一个窗口,从前向后滑动,如果窗口内和小于target就向右增大窗口,大于等于就向右滑动窗口,并尝试向左减小窗口。
int minSubArrayLen(int target, vector<int>& nums) {
int len = nums.size();
if (nums[0] >= target) return 1;
int left = 0, right = 1;
int minLen = INT_MAX;
int winSum = nums[0];
while (right < nums.size()) {
// cout << left << " " << right << " " << winSum << " " << minLen << endl;
winSum += nums[right];
if (winSum < target) {
++right;
} else {
minLen = min(right - left + 1, minLen);
winSum += -nums[right] - nums[left++];
}
}
return minLen == INT_MAX ? 0 : minLen;
}
虽然做出来了,但是感觉思路不是很清晰,还是照着模板来吧,这样做的会快一点?
窗口内: 总和sum大于target的最短连续子数组
如何移动窗口起始值:如果当前窗口内总和sum >= target就要缩小窗口
如何移动窗口最大值:如果当前窗口内总和sum < target 就要扩充窗口
int minSubArrayLen(int target, vector<int>& nums) {
int left = 0; // 记录滑动窗口起始值
int numsLen = nums.size();
int minLen = INT_MAX; // 记录窗口最小长度
int sum = 0; // 记录窗口内数字和
for(int right = 0; right < numsLen; right++) {
sum += nums[right]; // 窗口逐渐左移
while(sum >= target) { // 满足条件开始缩小窗口
minLen = min(minLen, right - left + 1);
sum -= nums[left++]; // 缩小左边界
}
}
return minLen == INT_MAX ? 0 : minLen;
}
59.螺旋矩阵II
思路: 模拟填充矩形。从左到右,从上到下,从右到左,从下到上。
一共有n*n次赋值,循环结束条件是填充 N * N次。
int times = 0;
int top = 0, left = 0, bottom = n - 1, right = n - 1;
while(times < n * n) {
for(int i = left; i <= right; i++)
res[top][i] = ++times;
++top;
for(int i = top; i <= bottom; i++)
res[i][right] = ++times;
--right;
for(int i = right; i >= left; i--)
res[bottom][i] = ++times;
--bottom;
for(int i = bottom; i >= top; i--)
res[i][left] = ++times;
++left;
}