文章目录
- 前言
- 一、977.有序数组的平方
- 二、209.长度最小的子数组
- 三、59.螺旋矩阵
- 总结
前言
java版:
代码随想录算法训练营第二天 | 977.有序数组的平方 ,209.长度最小的子数组 ,59.螺旋矩阵_愚者__的博客-CSDN博客
一、977.有序数组的平方
双指针法:
int* sortedSquares(int* nums, int numsSize, int* returnSize){
*returnSize = numsSize;
int right = numsSize -1 ;
int left = 0;
int* ans = (int*)malloc(sizeof(int) * numsSize);
int index;
for(int index = numsSize-1;index>=0;index--){
int lSquare = nums[left]*nums[left];
int rSquare = nums[right]*nums[right];
if(lSquare > rSquare){
ans[index] = lSquare;
left++;
}else{
ans[index] = rSquare;
right--;
}
}
return ans;
}
二、209.长度最小的子数组
滑动窗口:本质是满足了单调性,即左右指针只会往一个方向走且不会回头。收缩的本质即去掉不再需要的元素。也就是做题我们可以先固定移动右指针,判断条件是否可以收缩左指针算范围。
加入滑动窗口中有负数怎么办?
如果有负数的话感觉也不能用滑动窗口了,因为有负数的话无论你收缩还是扩张窗口,你里面的值的总和都可能增加或减少,就不像之前收缩一定变小,扩张一定变大,一切就变得不可控了。如果要 cover 所有的情况,那每次 left 都要缩到 right,那就退化为暴力了哈哈。
双指针和滑动窗口有什么区别,感觉双指针也是不断缩小的窗口。这道题,我想用两头取值的双指针,结果错了?
因为两头指针走完相当于最多只把整个数组遍历一遍,会漏掉很多情况。滑动窗口实际上是双层遍历的优化版本,而双指针其实只有一层遍历,只不过是从头尾开始遍历的。
int minSubArrayLen(int target, int* nums, int numsSize){
int minLength = INT_MAX;
int sum = 0;
int left = 0;
int right = 0;
for(;right<numsSize;right++){
sum += nums[right];
while(sum >= target){
int subLength = right - left + 1;
minLength = minLength<subLength?minLength: subLength;
sum -= nums[left];
left++;
}
}
return minLength == INT_MAX?0:minLength;
}
三、59.螺旋矩阵
坚持循环不变量原则。
模拟顺时针画矩阵的过程:
- 填充上行从左到右
- 填充右列从上到下
- 填充下行从右到左
- 填充左列从下到上
由外向内一圈一圈这么画下去。
可以发现这里的边界条件非常多,在一个循环中,如此多的边界条件,如果不按照固定规则来遍历,那就是一进循环深似海,从此offer是路人。
int** generateMatrix(int n, int* returnSize, int** returnColumnSizes){
//初始化返回的结果数组的大小
*returnSize = n;
*returnColumnSizes = (int*)malloc(sizeof(int) * n);
//初始化返回结果数组ans
int** ans = (int**)malloc(sizeof(int*) * n);
int i;
for(i = 0; i < n; i++) {
ans[i] = (int*)malloc(sizeof(int) * n);
(*returnColumnSizes)[i] = n;
}
//设置每次循环的起始位置
int startX = 0;
int startY = 0;
//设置二维数组的中间值,若n为奇数。需要最后在中间填入数字
int mid = n / 2;
//循环圈数
int loop = n / 2;
//偏移数
int offset = 1;
//当前要添加的元素
int count = 1;
while(loop) {
int i = startX;
int j = startY;
//模拟上侧从左到右
for(; j < n - offset; j++) {
ans[i][j] = count++;
}
//模拟右侧从上到下
for(; i < n - offset; i++) {
ans[i][j] = count++;
}
//模拟下侧从右到左
for(; j > startY; j--) {
ans[i][j] = count++;
}
//模拟左侧从下到上
for(; i > startX; i--) {
ans[i][j] = count++;
}
//偏移值每次加2
offset+=1;
//遍历起始位置每次+1
startX++;
startY++;
loop--;
}
//若n为奇数需要单独给矩阵中间赋值
if(n%2)
ans[mid][mid] = count;
return ans;
}
总结
附加题这周闲下来再补。