今天是6.9,正值端午假期,没啥事把前天的博客补一下哈哈哈,补进度的感觉可太难受了。。。
每道题的方法:
977:利用双指针法,两个指针分别从数组的两遍(两边是较大的值)遍历去填充新容器。
209:利用双指针法,从同一个地方开始移动,但是先移动终止指针,再通过while循环移动起始指针,不断改变窗口的位置和大小。
59:因为是填充二维数组所以也相当于利用双指针法,不过每次循环注意遵循循环不变量的原则,同时还需要注意通过改变一些值来控制边界。
题目一链接:977. 有序数组的平方 - 力扣(LeetCode)
思路:构造一个与nums大小一样的容器result,然后利用i,j两个指针遍历两边取最大值(nums数组的特性:平方后较大值在两侧)再利用slow指针反向填充(因为要求递增的顺序)result容器。
代码:
class Solution {
public:
vector<int> sortedSquares(vector<int>& nums) {
//先将数组每个数都平方
for(int i = 0;i < nums.size();i ++) {
nums[i] *= nums[i];
}
//定义一个新的result容器
int n = nums.size();
vector <int> result(n,0);
//slow用来填充新的result容器
int slow = n - 1;//从最后开始填充
//定义i,j两个指针
for(int i = 0,j = n - 1;i <= j;) {//nums两侧的数平方后有最大值
if(nums[j] >= nums[i]) {
result[slow --] = nums[j];
j --;
}
else {
result[slow --] = nums[i];
i ++;
}
}
return result;
}
};
难点:
解释细节4:通过观察可得,所以要求两个指针从两侧开始向中间靠拢来便利nums。
解释错误点2:slow应该从nums.size() - 1,开始
题目二链接:59. 螺旋矩阵 II - 力扣(LeetCode)
思路:遵循左闭右开的原则进行很多圈的遍历和赋值。
代码:
class Solution {
public:
vector<vector<int>> generateMatrix(int n) {
vector<vector<int>> res(n,vector<int>(n,0));
int startx = 0,starty = 0;//定义每一圈的起始位置,
int loop = n / 2;//控制遍历的圈数
int mid = n / 2;//如果n为奇数的话,最后得考虑最中间的那个点
int count = 1;//用来给每一位赋值
int offset = 1; 需要控制每一条边遍历的长度,每次循环右边界收缩一位:第一圈是减一,后面逐渐递增
int i,j;//用来便利整个矩阵
while(loop --) {
//改变每一圈开始遍历的位置
i = startx;
j = starty;
//第一圈遍历:
for(j;j < n - offset;j ++) {
res[i][j] = count ++;
}
for(i;i < n - offset;i ++) {
res[i][j] = count ++;
}
for(j;j > starty;j --) {//遵循左闭右开的原则
res[i][j] = count ++;
}
for(i;i > startx;i --) {
res[i][j] = count ++;
}
//控制每一条边遍历的长度
offset ++;
//改变每一圈开始遍历的位置
startx ++;
starty ++;
}
if(n % 2 != 0) res[mid][mid] = count;
return res;
}
};
难点:
解释细节1:因为遵循循环不变量:区间左闭右开。
解释细节5:奇数时只需要在正中间加一个数
额外细节:二维数组的定义: res(n,vector<int>(n,0))
题目三链接:209. 长度最小的子数组 - 力扣(LeetCode)
思路:通过两个cur指针(有一个需要提前移动)遍历两个链表来寻找两个单链表的第一个相同节点(指的是LinkedNode,而不是节点的值),然后输出节点即可。
代码:
class Solution {
public:
int minSubArrayLen(int target, vector<int>& nums) {
//定义最大值
int result = INT32_MAX;
int sum = 0;
for(int j = 0,i = 0;j < nums.size();j ++) {//j 代表终止位置
//起始位置移动的逻辑:
sum += nums[j];
while(sum >= target) {//写完if后发现后面需要不断循环这个过程,所以这里是while而不是if
int subl = j - i + 1;
res = min(res,subl);
sum -= nums[i ++];
}
}
if(res == INT32_MAX) return 0;
else return res;
}
};
难点:
解释细节2:当通过移动终止位置而求出的sum大于target时再移动起始位置。
解释细节3:写完if后发现后面需要不断循环这个过程,所以这里是while而不是if