977、有序数组的平方
给你一个按 **非递减顺序** 排序的整数数组 `nums`,返回 **每个数字的平方** 组成的新数组,要求也按 **非递减顺序** 排序。
**示例 1:**
**输入:**nums = [-4,-1,0,3,10]
**输出:**[0,1,9,16,100]
**解释:**平方后,数组变为 [16,1,0,9,100]
排序后,数组变为 [0,1,9,16,100]
**示例 2:**
**输入:**nums = [-7,-3,2,3,11]
**输出:**[4,9,9,49,121]
想法:这道题刚拿到手,Carl建议使用双指针,于是从双指针入手
这个 `sortedSquares` 方法接受一个整数数组 `nums` 作为输入,其中可能包含正数和负数。它对数组中的每个元素进行平方,将平方值按非递减顺序排序,并返回结果数组。
这是算法的详细步骤:
1. 初始化两个指针,`left` 指向数组的起始位置(`0`),`right` 指向数组的末尾(`nums.length - 1`)。
2. 创建一个新数组 `result`,用于存储平方后的值,长度与输入数组 `nums` 相同。
3. 初始化一个 `index` 变量,指向 `result` 数组的最后一个索引(`result.length - 1`)。
4. 使用 while 循环遍历数组 `nums`,直到 `left` 指针小于等于 `right` 指针。
5. 比较 `left` 和 `right` 指针处数字的平方。
6. 如果 `left` 指针处数字的平方大于 `right` 指针处数字的平方,将 `left` 指针处数字的平方插入到 `result` 数组的 `index` 位置,并将 `left` 指针向右移动一位。
7. 否则,将 `right` 指针处数字的平方插入到 `result` 数组的 `index` 位置,并将 `right` 指针向左移动一位。
8. 将 `index` 变量减一。
9. 循环结束后,`result` 数组将包含按非递减顺序排序的 `nums` 数组中元素的平方值。
这个算法利用了负数的平方是按降序排列的,而正数的平方是按升序排列的这一事实。因此,当合并两个已排序的半段(正数平方和负数平方)时,我们只需比较两端的值,以确定应将哪个值插入到结果数组中。
代码:
class Solution {
public int[] sortedSquares(int[] nums) {
int left = 0;
int right = nums.length-1;
int[] result = new int[nums.length];
int index = result.length-1;
while(left<=right){
if(nums[left]*nums[left]>nums[right]*nums[right]){
result[index--]=nums[left]*nums[left];
left++;
}
else{
result[index--]=nums[right]*nums[right];
right--;
}
}
return result;
}
}
209、长度最小的子数组
给定一个含有 `n` 个正整数的数组和一个正整数 `target` **。**
找出该数组中满足其总和大于等于 `target` 的长度最小的 **连续**
**子数组**
`[numsl, numsl+1, ..., numsr-1, numsr]` ,并返回其长度**。**如果不存在符合条件的子数组,返回 `0` 。
**示例 1:**
**输入:**target = 7, nums = [2,3,1,2,4,3]
**输出:**2
**解释:**子数组 `[4,3]` 是该条件下的长度最小的子数组。
**示例 2:**
**输入:**target = 4, nums = [1,4,4]
**输出:**1
**示例 3:**
**输入:**target = 11, nums = [1,1,1,1,1,1,1,1]
**输出:**0
本题关键在于理解滑动窗口,相当于用一个for循环做两个for循环要做的事情,right指向滑动窗口里的终止位置,所以要思考如何移动起始位置。
当我们起点和终点这个集合里面的元素>=target,说明这是符合条件的集合,收集当前的长度之后,起始位置就可以向后移动,再缩小现在的集合,来看下一个集合是否符合条件。
这里是算法的详细步骤:
1. 初始化两个指针 `left` 和 `right`,都指向数组的起始位置(`0`)。
2. 初始化一个变量 `result` 为整数的最大值 `Integer.MAX_VALUE`,用于存储找到的最短子数组的长度。
3. 初始化一个变量 `sum` 为 `0`,用于计算当前子数组的和。
4. 使用 `for` 循环遍历数组 `nums`,其中 `right` 指针从 `0` 开始,直到数组的末尾。
5. 在循环中,累加 `nums[right]` 到 `sum` 中。
6. 使用 `while` 循环,当 `sum` 大于或等于 `target` 时,执行以下操作:
- 更新 `result` 为当前子数组的长度 `right - left + 1` 和 `result` 之间的较小值。
- 从 `sum` 中减去 `nums[left]`。
- 将 `left` 指针向右移动一位。
7. 重复步骤 5 和 6,直到 `right` 指针遍历完整个数组。
8. 返回 `result`,如果 `result` 仍然是 `Integer.MAX_VALUE`,则返回 `0`,表示数组中没有和大于或等于 `target` 的子数组。
这个算法使用了滑动窗口的技巧,通过移动 `left` 和 `right` 指针来动态地调整子数组的范围,并在满足条件时更新最短子数组的长度。这样可以在 `O(n)` 的时间复杂度内找到结果,其中 `n` 是数组 `nums` 的长度。
实现代码:
class Solution {
public int minSubArrayLen(int target, int[] nums) {
int left = 0;
int right = 0;
int result = Integer.MAX_VALUE;
int sum = 0;
for(right = 0;right < nums.length;right++){
sum = sum + nums[right];
while(sum >= target){
result = Math.min(result,right-left+1);
sum = sum - nums[left];
left++;
}
}
return result == Integer.MAX_VALUE ? 0 : result;
}
}
59、螺旋矩阵Ⅱ
给你一个正整数 `n` ,生成一个包含 `1` 到 n的平方的 所有元素,且元素按顺时针顺序螺旋排列的 `n x n` 正方形矩阵 `matrix` 。
**示例 1:**
![](https://assets.leetcode.com/uploads/2020/11/13/spiraln.jpg)
**输入:**n = 3
**输出:**[[1,2,3],[8,9,4],[7,6,5]]
**示例 2:**
**输入:**n = 1
**输出:**[[1]]
算法的详细步骤:
1. 初始化四个变量 `l`、`r`、`t`、`b`,分别表示当前填充的矩阵边界的左、右、上、下位置,初始值都为 `0` 到 `n - 1`。
2. 创建一个大小为 `n x n` 的二维数组 `mat`,用于存储生成的螺旋矩阵。
3. 初始化两个变量 `num` 和 `tar`,分别表示当前填充的数字和总共需要填充的数字数量,初始值分别为 `1` 和 `n x n`。
4. 使用 `while` 循环,循环条件是 `num` 小于等于 `tar`,即还未填充完整个矩阵。
5. 在循环中,依次执行以下步骤:
- 从左到右:使用 `for` 循环填充当前行 `t`,列从 `l` 到 `r`,填入数字 `num`,并递增 `num`。
- 更新上边界 `t`,向下移动一行。
- 从上到下:使用 `for` 循环填充当前列 `r`,行从 `t` 到 `b`,填入数字 `num`,并递增 `num`。
- 更新右边界 `r`,向左收缩一列。
- 从右到左:使用 `for` 循环填充当前行 `b`,列从 `r` 到 `l`,填入数字 `num`,并递增 `num`。
- 更新下边界 `b`,向上收缩一行。
- 从下到上:使用 `for` 循环填充当前列 `l`,行从 `b` 到 `t`,填入数字 `num`,并递增 `num`。
- 更新左边界 `l`,向右移动一列。
6. 循环结束后,所有数字都已经填充完毕,返回生成的螺旋矩阵 `mat`。这个算法通过不断更新边界位置和填充数字,按照顺时针螺旋的方式逐步生成完整的矩阵。
代码如下所示:
class Solution {
public int[][] generateMatrix(int n) {
int l = 0, r = n - 1, t = 0, b = n - 1;
int[][] mat = new int[n][n];
int num = 1, tar = n * n;
while(num <= tar){
for(int i = l; i <= r; i++) mat[t][i] = num++; // left to right.
t++;
for(int i = t; i <= b; i++) mat[i][r] = num++; // top to bottom.
r--;
for(int i = r; i >= l; i--) mat[b][i] = num++; // right to left.
b--;
for(int i = b; i >= t; i--) mat[i][l] = num++; // bottom to top.
l++;
}
return mat;
}
}