代码随想录刷题Day2 | 977.有序数组的平方 ,209.长度最小的子数组 ,59.螺旋矩阵II
977.有序数组的平方
题目: 给你一个按 非递减顺序 排序的整数数组 nums
,返回 每个数字的平方 组成的新数组,要求也按 非递减顺序 排序。
思路:
- 暴力解法:对数组中的每个数字平方,然后重新排序,时间复杂度为较高(不同的排序算法有不同的时间复杂度)
- 双指针解法:左指针指向最左边元素,右指针指向最右边元素,比较绝对值的大小,首先计算绝对值最大的元素的平方,然后向中间移动该指针,循环该步骤,得到非递减顺序的每个数字的平方的排序,然后反转该数组。
代码:
class Solution {
public int[] sortedSquares(int[] nums) {
int left = 0, right = nums.length - 1, len = nums.length - 1;
int[] result = new int[nums.length];
while(len >= 0){
if(Math.abs(nums[left]) <= Math.abs(nums[right])){
result[len] = nums[right] * nums[right];
right--;
}else{
result[len] = nums[left] * nums[left];
left++;
}
len--;
}
return result;
}
}
时间复杂度:O(n),空间复杂度:O(n)
209.长度最小的子数组
题目: 给定一个含有n
个正整数的数组和一个正整数 target
。找出该数组中满足其和 ≥ target
的长度最小的 连续子数组[numsl, numsl+1, ..., numsr-1, numsr]
,并返回其长度。如果不存在符合条件的子数组,返回 0 。
思路: 采用划定窗口的形式,也就是双指针,一个指针指向窗口的头部,定义为right,一个指针指向窗口的尾部,为left,初始时,两个指针均指向index为0的位置,right指针开始遍历nums数组,当left到right之间的值的和大于target时,left开始移动到和小于target,然后继续移动right直至最后。(如果遇到nums[right]>target直接返回1)
代码:
class Solution {
public int minSubArrayLen(int target, int[] nums) {
int left = 0, right = 0, result = Integer.MAX_VALUE, sum = 0;
while(right <= nums.length - 1){
if(nums[right] >= target) return 1;
sum += nums[right];
while(sum >= target){
sum -= nums[left++];
result = right - left + 2 < result ? right - left + 2 : result;
}
right++;
}
return result > nums.length ? 0 : result;
}
}
时间复杂度:O(n),空间复杂度O(1)
59.螺旋矩阵II
题目: 给你一个正整数 n
,生成一个包含 1
到 n2
所有元素,且元素按顺时针顺序螺旋排列的 n x n
正方形矩阵 matrix
。
示例:
输入:n = 3
输出:[[1,2,3],[8,9,4],[7,6,5]]
思路: 模拟该算法,定义dir变量代表四个方向,到边界时换到下一个方向。边界判断方法为:1. 到达边界,比如上图中的3 2.下一个位置已经遍历过,比如说上图中的8
代码:
class Solution {
public int[][] generateMatrix(int n) {
int[][] result = new int[n][n];
int dir = 0;//定义方向变量,0,1,2,3代表不同的方向,每次改变方向,dir + 1
int i = 0, j = 0;
for(int num = 1; num <= n* n; num++){
if(dir % 4 == 0){
result[i][j] = num;
if(j == n - 1 || result[i][j+1] != 0){
i++;
dir++;
continue;
}
j++;
}else if(dir % 4 == 1){
result[i][j] = num;
if(i == n - 1 || result[i+1][j] != 0){
j--;
dir++;
continue;
}
i++;
}else if(dir % 4 == 2){
result[i][j] = num;
if(j == 0 || result[i][j-1] != 0){
i--;
dir++;
continue;
}
j--;
}else if(dir % 4 == 3){
result[i][j] = num;
if(result[i-1][j] != 0){
j++;
dir++;
continue;
}
i--;
}
}
return result;
}
}
时间复杂度为O(nxn),空间复杂度为O(nxn)
总结
- 对于有序不重复数组,使用二分查找更加简单快捷,使用二分查找时,注意边界情况。
- 数组不能删除,只能覆盖。
- 双指针可以使一些数组的操作变得简单,遇到数组相关的问题,可以先想一下是否可以使用双指针,一般使用双指针的形式有快慢指针,和指向两端的双指针。
- 滑动窗口也是一种特殊的双指针形式,要注意什么时间移动哪一个指针。
查找时,注意边界情况。
2. 数组不能删除,只能覆盖。
3. 双指针可以使一些数组的操作变得简单,遇到数组相关的问题,可以先想一下是否可以使用双指针,一般使用双指针的形式有快慢指针,和指向两端的双指针。
4. 滑动窗口也是一种特殊的双指针形式,要注意什么时间移动哪一个指针。