见 LeetCode刷题笔记【1】:数组专题-1
LeetCode链接:https://leetcode.cn/problems/squares-of-a-sorted-array/
在头部和尾部分别设置一个指针,比较这两个指针指向的元素的绝对值的大小(或者平方的大小),大的就先进数组,对应的指针移动。
直到两个指针相遇。
// 头尾双指针, 谁的平方大就在前面, 依次移动, 直到二者相等
class Solution {
public:
vector<int> sortedSquares(vector<int>& nums) {
int n=nums.size();
int head=0, tail=n-1;
vector<int> ans(n);
while(head<=tail){
int headVal = nums[head]*nums[head];
int tailVal = nums[tail]*nums[tail];
if(headVal>=tailVal){
ans[n-1] = headVal;
++head;
}else{
ans[n-1] = tailVal;
--tail;
}
--n;
}
return ans;
}
};
LeetCode链接:https://leetcode.cn/problems/minimum-size-subarray-sum/
依次遍历每个元素, 向后生长出一个包括当前元素的子数组, 一直生长到其和>=target, 或者抵达数组结尾, 然后记录其大小, 取最小值
class Solution {
public:
int minSubArrayLen(int target, vector<int>& nums) {
int n=nums.size();
int ans=INT_MAX, curSize, curVal;
for(int i=0; i<n; ++i){
curSize = 0;
curVal = 0;
for(int j=i; j<n; j++){
++curSize;
curVal += nums[j];
if(curVal>=target){
ans = min(ans, curSize);
break;
}
}
}
return ans==INT_MAX ? 0 : ans;
}
};
暴力求解时间复杂度过高, 无法通过.
观察暴力求解法需要反复遍历数组, 思考是否可以一次遍历数组就达到要求.
方法就是构建一个由两个指针组成的窗口, 从头到尾地遍历过去.
// 先从头开始生长(右移right)一个窗口, 直到满足curVal>=target
// 然后开始左移left, 直到不满足curVal>=target
// 然后继续右移right
class Solution {
public:
int minSubArrayLen(int target, vector<int>& nums) {
if(nums[0]>=target)
return 1;
int n=nums.size();
int ans=INT_MAX, curSize=1, curVal=nums[0];
int left=0, right=1;
while(left<n && right<n){
curVal += nums[right];
curSize++;
while(curVal>=target){
ans = min(ans, curSize);
curVal -= nums[left];
curSize--;
left++;
}
right ++;
}
return ans==INT_MAX ? 0 : ans;
}
};
LeetCode链接:https://leetcode.cn/problems/spiral-matrix-ii/
对于模拟类的题目, 或许存在简便做法, 但是大部分情况都是他怎么说你怎么做.
这一题的难点在于厘清和确定循环的边界和过程.
把每一圈的遍历抽出来, 发现每次都是从[startX, startY]处开始, 然后走四个边.
于是每一圈都递增startX和startY, 并且用递增的offset来帮助做遍历.
class Solution {
public:
vector<vector<int>> generateMatrix(int n) {
vector<vector<int>> ans(n, vector<int>(n));
int curVal=1, target=n*n, startX=0, startY=0, offset=1, loop=n/2;
while(loop--){
int y=startY;
int x=startX;
for(y=startY; y<n-offset; ++y){
cout << "1 " << x << " " << y << " " << curVal << endl;
ans[x][y] = curVal++;
}
for(x=startX; x<n-offset; ++x){
cout << "2 " << x << " " << y << " " << curVal << endl;
ans[x][y] = curVal++;
}
for(; y>startY; y--){
cout << "3 " << x << " " << y << " " << curVal << endl;
ans[x][y] = curVal++;
}
for(; x>startX; x--){
cout << "4 " << x << " " << y << " " << curVal << endl;
ans[x][y] = curVal++;
}
startX++;
startY++;
offset++;
}
if(n%2){
ans[n/2][n/2] = curVal;
}
return ans;
}
};
多指针的方法确实好用, 关键是要对数组的操作有清晰明确的思路和概念.
同时哟啊注意各种边界情况.
本文参考:
977.有序数组的平方
209.长度最小的子数组
59.螺旋矩阵II