打卡第二天,学习算法的同时回顾SQL和Linux知识。
1、有序数组的平方
关键是如何想到用双指针法?原数组有序,结果数组有序,原数组元素平方后,一定是两边大中间逐渐减小。
写码的问题直接随手注释。
class Solution {
public:
vector<int> sortedSquares(vector<int>& nums) {
int k = nums.size() - 1;
vector<int> result(nums.size(), 0);//注意此句设置结果数组写法
for ( int i = 0, j = nums.size() - 1; i <= j ; ){//如果只写i<j,若有中间两数相等,循环会跳出,少更新一个元素
//i和j的更新都需要一定条件,因此不写在for循环条件中
//小错误,定义j时不用再写个int;也不要忘了-1
if ( nums[i] * nums[i] < nums[j] * nums[j] ){
result[k--] = nums[j]*nums[j];//注意把k--放在这里的写法
j--;
}else {
result[k--] = nums[i]*nums[i];
i++;
}
}
return result;
}
};
理解思路应当不难,但想到这个方法和代码细节很重要。养成良好习惯。
2、长度最小的子数组
原理是右边先开始走,然后直到窗口内值的总和大于target,此时就开始缩圈,缩圈是为了找到最小值,只要此时总和还大于target,我就一直缩小,缩小到小于target为止在这过程中不断更新最小的长度值,然后右边继续走,如此反复,直到右边碰到边界。
关键是1、先固定移动右指针,判断条件是否可以收缩左指针算范围。2、在双指针中如何移动起始位置的指针?起始位置的指针要持续向后移动,更新滑动窗口。3、里面不能有负数。
class Solution {
public:
int minSubArrayLen(int target, vector<int>& nums) {
int result = nums.size();//应设为INT32_MAX最大值
int i = 0;
int sum = 0;
int subl = 0;
for (int j = 0; j < nums.size(); j++){
sum += nums[j];
while (sum >= target){
//用while不用if因为需要不断更新起始指针
subl = j - i + 1;
result = result < subl ? result : subl; //注意这里的比较大小写法
sum = sum - nums[i];
i++;//起始指针移动
}
}
return result == nums.size() ? 0 : result;//注意这句的写法
}
};
错误点:在最后返回结果时应考虑到没有满足条件的窗口的情况
3、螺旋矩阵II
第一个中等题
原理是坚持循环不变量原则,让每种(即填充上部右部下部左部的哪部)填充操作保持相同样式的循环:通过offset预留位置。按上右下左的顺序依次填入递增的数。要留意while何时退出。
一些注意点随手写在注释里:
每一圈循环的起始横下标,在转完一圈以后更新
每一圈循环的起始纵下标,在转完一圈以后更新
每圈上部,从左到右递增,留offset个位置,所以填到下标为n-offset为止
每圈右部,从上到下递增,留offset个位置,所以填到下标n-offset为止
每圈下部,从右到左递增,留offset个位置,所以填到下标offset-1或startx为止
每圈左部,从下到上递增,留offset个位置,所以填到下标offset-1或starty为止
每次循环初始位置下标+1
每次循环预留位置下标+1
class Solution {
public:
vector<vector<int>> generateMatrix(int n) {
vector<vector<int>> nums(n, vector<int>(n, 0));//初始化二维数组矩阵
int startx = 0;//每一圈循环的起始横下标,在转完一圈以后更新
int starty = 0;//每一圈循环的起始纵下标,在转完一圈以后更新
int offset = 1;//转的第几圈,边缘就要空出几个位置
int loop = n / 2;
int count = 1;
int i,j;
while (loop --){
i = startx;
j = starty;//提前声明,防止在for循环内声明时作用不到外部
//每圈上部,从左到右递增,留offset个位置,所以填到下标为n-offset为止
for(j; j < n - offset; j++){
nums[startx][j] = count++;//i不变,按j递增赋值count
}
//每圈右部,从上到下递增,留offset个位置,所以填到下标n-offset为止
for(i; i < n - offset; i++){
nums[i][j] = count++;//j不变,按i递增赋值count
}
//每圈下部,从右到左递增,留offset个位置,所以填到下标offset-1或startx为止
for(;j > offset - 1; j--){
nums[i][j] = count++;//i不变,按j递减赋值count
}
//每圈左部,从下到上递增,留offset个位置,所以填到下标offset-1或starty为止
for(;i > offset - 1; i--){
nums[i][j] = count++;//j不变,按i递减赋值count
}
startx++;//每次循环初始位置下标+1
starty++;//每次循环初始位置下标+1
offset++;//每次循环预留位置下标+1
}
//如果n是奇数,需要填充中心位置的元素,但要注意此时的数组下标
if(n%2 == 1){
nums[startx][starty] = count;// 或者先预设mid=n/2,填充的就是nums[mid][mid],例如:n为3, 中间的位置就是(1,1),n为5,中间位置为(2, 2)
}
return nums;
}
};
错误点:1、基础的参数声明,要明确参数作用的范围。2、注意while条件的写法。3、n是奇数的情况,中心位置填充时数组下标应该怎么样填。
明天继续加油。