代码随想录算法训练营第2天 | 977.有序数组的平方 、209.长度最小的子数组 、 59.螺旋矩阵II
977.有序数组的平方
class Solution {
public int[] sortedSquares(int[] nums) {
int right = nums.length - 1;
int left = 0;
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.长度最小的子数组
暴力且错误
class Solution {
public int minSubArrayLen(int target, int[] nums) {
int size = 0;
int sum = 0;
for(int i = 0;i < nums.length;i++){
int maxIndex = i;
for(int j = i + 1;j < nums.length;j++){
if(nums[maxIndex] >= target){
return 1;
}
if(nums[maxIndex] < nums[j]){
maxIndex = j;
}
}
System.out.println("maxIndex:" + maxIndex);
System.out.println("nums[maxIndex]:" + nums[maxIndex]);
exchange(nums,maxIndex,i);
sum += nums[i];
System.out.println("sum:" + sum);
size++;
System.out.println("size:" + size);
if(sum >= target){
return size;
}
}
return 0;
}
public void exchange(int[] nums,int i,int j){
int flag = nums[j];
nums[j] = nums[i];
nums[i] = flag;
}
}
没看清题,要求的连续子数组
所以213 [12,28,83,4,25,26,25,2,25,25,25,12]该测试案例则会不通过
滑动窗口
滑动窗口的本质就是两个指针所包围的区间
思路
- 明确
j
代表滑动窗口的终点位置,i
代表滑动窗口的起始位置 - 首先让
j
不断右移直至i
与j
的窗口所包含的所有的值 和 >= target, - 再让
i
右移,直至 找到 满足和 >= target 的最小区间 , 找到后i的位置是新的起点,且此时 sum < target - 不断重复2,3步骤
代码
class Solution {
// 滑动窗口
public int minSubArrayLen(int s, int[] nums) {
int left = 0;
int sum = 0;
int result = Integer.MAX_VALUE;
for (int right = 0; right < nums.length; right++) {
sum += nums[right];
while (sum >= s) {
result = Math.min(result, right - left + 1);
sum -= nums[left++];
}
}
return result == Integer.MAX_VALUE ? 0 : result;
}
}
注意初始不要让result等于数组长度,不然会影响最后的判断
59.螺旋矩阵II
思路
模拟每条边的赋值过程
核心:
- 起始点、圈数、边界点的设置
- 循环不变量,即进行单条边的赋值规则应该需要统一,此题每条单边赋值都是左闭右开(起始赋值,终点没赋值)
代码
class Solution {
public int[][] generateMatrix(int n) {
int loop = 0; // 控制循环次数
int[][] res = new int[n][n];
int start = 0; // 每次循环的开始点(start, start)
int count = 1; // 定义填充数字
int i, j;
while (loop++ < n / 2) { // 判断边界后,loop从1开始
// 模拟上侧从左到右
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;
}
}