代码随想录算法训练营day2:
学习内容:
今天继续学习数组。
学习产出:
用肌肉记忆写成了双指针法(相向):
class Solution {
public:
vector<int> sortedSquares(vector<int>& nums) {
int start=0,end=nums.size()-1;
int newend=nums.size()-1;
vector<int> final(nums.size());//创建新的输出向量,初始化为同长度的全0向量
while(newend>=0){
if (abs(nums[start])>abs(nums[end])){//双指针法,因为知道nums从负到正递增,左边是绝对值最大的负数,右边是最大的正数,所以按平方值递增就是绝对值的较量
final[newend]=nums[start];//如果绝对值最大的负数大于绝对值最大的正数,就把它放在输出向量的最右边
start++;//左指针向右移动,因为最左的负数被填入了新vector的最右,下一轮由绝对值次大的负数和绝对值最大的正数比
newend--;//新向量是从大到小的顺序填充,所以最大的位置在此轮被填充,位次向左减一
}else{
final[newend]=nums[end];//如果是正数这边更大同理
end--;
newend--;
}
}
for(int i=0;i<final.size();++i){
final[i]=final[i]*final[i];//将填充好的新向量的所有元素更新为各自的平方,满足题设所需的输出
}
return final;}
};
滑动窗口法,关键在于两个while循环要写对,窗口先向右扩展(while)探索满足条件的子数组,满足后再缩小(while)直到不满足条件然后继续向右扩展;这个过程要记录产生的最小子数组的长度。直到窗口右端触底并且不能再缩小。(a<=b;b<size())
class Solution {
public:
int minSubArrayLen(int target, vector<int>& nums) {
int a=0,b=0;
int sum=0,min_len=0;
while(a<=b&&b<nums.size()){
for(;b<nums.size();b++){
sum=sum+nums[b];
while(sum>=target){
if(min_len==0||b-a+1<min_len){
min_len=b-a+1;
}
sum=sum-nums[a];
a++;
}
}
}
return min_len;
}
};
这题还是比较有难度的,最难的点在于边界条件和初始值的设置把握,需要常看常新。
模拟过程为:
class Solution {
public:
vector<vector<int>> generateMatrix(int n) {
vector<vector<int>> matrix(n,vector<int>(n,0));
int i=0,j=0,offset=1,loop=0,num=1;//offset等于1,因为一开始圈每条边输入长度为n-1;loop等于0
int startx=0,starty=0;
int loop_max=n/2;//每一圈跑完,圈的边长度都减少2,直到没有边长,也就是从0跑到n/2-1共计n/2圈
while(loop<loop_max){
for(i=startx;i<n-offset;i++){
matrix[starty][i]=num;
num++;
}
for(j=starty;j<n-offset;j++){
matrix[j][i]=num;
num++;
}
for(;i>startx;i--){
matrix[j][i]=num;
num++;
}
for(;j>starty;j--){
matrix[j][i]=num;
num++;
}
startx++;
starty++;
offset+=1;//跑完一圈后,左边界都要向内收缩1
loop++;
}
if(n%2==1){
matrix[starty][startx]=num;//如果n是奇数,最后startx=starty=n/2,把最后一个数填入中心
}
return matrix;
}
};
数组总结:
1.二分法(注意边界,左开右闭,左闭右闭)
2.快慢指针法更新数组
3.双指针法
4.滑动窗口法
5.模拟过程