目录
一、看视频/文章讲解
1.977.有序数组的平方
感觉和相向双指针十分相似,而且允许额外复制一个数组后变得好理解多了。
2.209.长度最小的子数组
滑动窗口理解起来是真的很反常规,一般面对起始位置、终止位置都可变的情况,都会优先想用循环去控制起始位置(比如暴力法就是外层变量表示起始位置,内层变量表示终止位置),而滑动窗口是用循环去控制结束位置,再根据指定条件去控制起始位置
听到这里自己尝试去写了一下:
class Solution {
public:
int minSubArrayLen(int target, vector<int>& nums) {
int i=0;
int minLen=nums.size();
int findFlag=0;
for(int j=0;j<nums.size();j++){
int sum = 0;
for(int k=i;k<=j;k++){
sum += nums[k];
}
if(sum>=target){
int tempLen = j-i+1;
if(tempLen<=minLen){
minLen=tempLen;
findFlag=1;
}
i++;
j--;//起始位置后挪时终止位置维持不变
}
}
if(findFlag){
return minLen;
}else{
return 0;
}
}
};
好家伙,根据报错调试修改了2次,总算能跑过大多数测试用例了,结果竟然超时了,肯定是坏在了sum的累加上,毕竟i不动的情况下没必要每次都从头累加,再一次好了:
class Solution {
public:
int minSubArrayLen(int target, vector<int>& nums) {
int i=0;
int minLen=nums.size();
int findFlag=0;
int sum = 0;
for(int j=0;j<nums.size();j++){
sum += nums[j];
if(sum>=target){
int tempLen = j-i+1;
if(tempLen<=minLen){
minLen=tempLen;
findFlag=1;
}
sum = sum-nums[i]-nums[j];
i++;
j--; //起始位置往后挪的时候终止位置暂时不动
}
}
if(findFlag){
return minLen;
}else{
return 0;
}
}
};
竟然过了.....emmmmmm但是感觉自己写得...缝缝补补的
看完了视频可算是知道自己这缝缝补补的代码哪里怪了:
当起始位置需要连续后移时,我是用j--间接达到起始位置往后挪的时候终止位置暂时不动的目的的,这看起来远没有用while直观——起点需要向后移动到这个区间数值和小于目标值,然后才是终止位置的移动。
3.59.螺旋矩阵II
可以拿转的圈数作为结束循环的条件,用offset去表示每圈起始点的变化。
二、无提示动手做题
1.977.有序数组的平方
大概是因为昨天在学习双指针的时候有看这题的题解,而且有了相向双指针的经验,这题自己写得时候还算顺利(虽然还是犯了个非常脑瘫的错误,在对结果数组赋值时把result打成了nums,LeetCode上直接报错溢出,本地调试了才发现,可能是之前都是在原数组上操作打习惯了),但是我的循环的结束条件感觉写得是指向新数组的指针走到底,总觉得Carl的以左右指针重合为结束条件好像更加科学
class Solution {
public:
vector<int> sortedSquares(vector<int>& nums) {
vector<int> result(nums.size(),0);//todo 数组、指针、申明方式 此处为申明一个初始大小为nums.size()且初始值都为0的向量
int i=0,j=nums.size()-1;//指向原数组的左右指针
int k=j;//指向新数组的指针,因为原数组两端最大,所以从尾端开始赋值
while(k>=0){
if(nums[i]*nums[i]>nums[j]*nums[j]){
result[k--]=nums[i]*nums[i++];
}else{
result[k--]=nums[j]*nums[j--];
}
}
return result;
}
};
2.209.长度最小的子数组
这题看视频时写了
3.59.螺旋矩阵II
在这一题里终于有一点点理解左闭右闭/左闭右开区间了:
一开始我想用while(val<n*n)作为出循环条件,因为这样需要定义的变量是最少的,但是按照左闭右开区间的写法,当n为奇数时,最后一圈是只有一个格子要填的,而左闭右开区间在离散的数上是根本取不到一个数的,因为当区间两端取值相等时,左闭右开区间就不合法了。
如果改成左闭右闭区间的写法,n为奇数时最后一格就能被正常填到了,但是因为矩形的每个端点都会被重复填写,val的值会对不上,所以还是只能写左闭右开区间,再对n为奇数的情况“打个补丁”
这题我目前能写出来的,变量尽可能简明的代码如下
class Solution {
public:
vector<vector<int>> generateMatrix(int n) {
vector<vector<int>> res(n, vector<int>(n, 0)); // 使用vector定义一个二维数组
int round=1;
int offset=0;
int val = 1;
while(round<=n/2){
for(int i=0+offset,j=0+offset;j<n-1-offset;){
//结束循环的条件是j<n-1-offset意味着最后一个元素不填,边界处理原则——左闭右开区间
res[i][j]=val++;
j++;
}
for(int i=0+offset,j=n-1-offset;i<n-1-offset;){
res[i][j]=val++;
i++;
}
for(int i=n-1-offset,j=n-1-offset;j>0+offset;){
res[i][j]=val++;
j--;
}
for(int i=n-1-offset,j=0+offset;i>0+offset;){
res[i][j]=val++;
i--;
}
offset++;
round++;
}
if(n%2==1){//如果是奇数行则对中间位置进行单独赋值
res[n/2][n/2]=n*n;
}
return res;
}
};