代码随想录算法训练营十期
Day2 | 977.有序数组的平方 ,209.长度最小的子数组 ,59.螺旋矩阵II
977.有序数组的平方
题目链接:https://leetcode.cn/problems/squares-of-a-sorted-array/
class Solution {
public int[] sortedSquares(int[] nums) {
// 双指针法
// 数组其实是有序的, 只不过负数平方之后可能成为最大数了。
// 那么数组平方的最大值就在数组的两端,不是最左边就是最右边,不可能是中间。
// 此时可以考虑双指针法了,i指向起始位置,j指向终止位置。
// 定义一个新数组result,和A数组一样的大小,让k指向result数组终止位置。
// 如果A[i] * A[i] < A[j] * A[j] 那么result[k--] = A[j] * A[j];
// 如果A[i] * A[i] >= A[j] * A[j] 那么result[k--] = A[i] * A[i];
int len = nums.length;
int[] result = new int[len];
int j = nums.length-1;//注意是length-1
int i=0;
int index = result.length - 1;
// while (j >= i) {//注意是 >=
for (; i<=j;) {
int m = nums[i] * nums[i];
int n = nums[j] * nums[j];
if (m >= n) {
result[index--] = m;
i++;
} else {
result[index--] = n;
j--;
}
}
return result;
}
}
209.长度最小的子数组
题目链接:https://leetcode.cn/problems/minimum-size-subarray-sum/
class Solution {
public int minSubArrayLen(int target, int[] nums) {
//如何移动起始位置
int len=nums.length;
if(nums[len-1]==target){
return 1;
}
int min=1000000;
int p=0;
int count=0;
int num=0;
for (int q=0; q < len; q++) {
num+=nums[q];
while (num >= target){
count =q-p+1;
min=Math.min(count,min);
num-=nums[p++];
}
}
return min==1000000 ?0: min;
}
在本题中实现滑动窗口,主要确定如下三点:
- 窗口内是什么?
- 如何移动窗口的起始位置?
- 如何移动窗口的结束位置?
窗口就是 满足其和 ≥ s 的长度最小的 连续 子数组。
窗口的起始位置如何移动:如果当前窗口的值大于s了,窗口就要向前移动了(也就是该缩小了)。
窗口的结束位置如何移动:窗口的结束位置就是遍历数组的指针,也就是for循环里的索引。
解题的关键在于 窗口的起始位置如何移动,如图所示:
1 是从总共里面逐步减少而不是逐步增加
2 应该写if(sum >= target) 还是 while(sum >= target)?
- 时间复杂度:O(n)
- 空间复杂度:O(1)
59.螺旋矩阵II
题目链接:https://leetcode.cn/problems/spiral-matrix-ii/
class Solution {
public int[][] generateMatrix(int n) {
// 注意是必须要有圈数 圈数是重点
// 不能直接双层for一直判断
int[][] res = new int[n][n];
int loop = 0; // 控制循环次数
int i, j;
int start=0;
int count=1; //用来计数
while (loop++ < n/2) {
// 模拟上侧从左到右
for (j = start; j < n - loop; j++) {
res[start][j] = count++;
}
// 模拟右侧从上到下
for (i = start; i < n - loop; i++) {
res[i][j] = count++;
}
// 模拟下侧从右到左
for (; j >= loop; j--) {
res[i][j] = count++;
}
// 模拟左侧从下到上
for (; i >= loop; i--) {
res[i][j] = count++;
}
start++;
}
if (n % 2 == 1) {
res[start][start] = count;
}
return res;
}
}
- 第二个是不能for 需要while 控制层数
- 区间定义