977.有序数组的平方
class Solution {
public int[] sortedSquares(int[] nums) {
int i=nums.length-1;
int j=0;
int[] ans=new int[nums.length];
int n=nums.length-1;
while(n>=0){
int x=nums[i]*nums[i];
int y=nums[j]*nums[j];
if(x>=y){
ans[n]=x;
i--;
n--;
}else if(x<y){
ans[n]=y;
j++;
n--;
}
}
return ans;
}
}
就卡哥的答案来说,其核心思想其实就是双指针。
而相较于原地修改数据而言,这个题如果使用原地修改数据的话会让本来有序的数组乱序而导致题的难度和时间复杂度上升。
所以要利用好已经排序的这个数组,答案另外开辟一个数组来存储。
其核心就是从数组两端开始,因为指针指的负数平方后可能比另一个指针指的正数的平方大,所以从两头开始,找到大的那个放进数组后边,然后挪指针,直到数组被遍历完。其时间复杂度为
O(n)。
209.长度最小的子数组
这个题其实是一个标准滑动窗口的题,什么叫滑动窗口呢?个人理解是一个动态的子数组(用左右指针来截取,可以通过左指针前移除数据,右指针获得数据)
class Solution {
public int minSubArrayLen(int target, int[] nums) {
//滑动窗口,其实是一种双指针的写法
int i=-1;
int j=0;
//这个滑动窗口是一个双开区间
int sum=0;
int minLength=Integer.MAX_VALUE;
while(i!=j){
if(sum<target){
if(j>=nums.length) break;
sum+=nums[j++];
}else{
int len=j-i-1;
if(len<minLength){
minLength=len;
}
//然后将i指针左移
sum-=nums[++i];
}
}
return minLength==Integer.MAX_VALUE?0:minLength;
}
}
我的思路是一样的,但是我在控制循环的时候没有像卡哥的例题一样采用内部的while循环来控制左指针的移动,而是在右指针达到nums.length时左指针也不会移动就跳出循环。这样写感觉没有那样优雅,但是这是我自己写的不想改哈哈。
59.螺旋矩阵
class Solution {
public int[][] generateMatrix(int n) {
int[][] ans=new int[n][n];
int x=1;
int k=0;
while(k!=n/2){
int i=k;
int j=k;
while(j<n-1-k){
ans[i][j]=x++;
j++;
}
while(i<n-1-k){
ans[i][j]=x++;
i++;
}
while(j>k){
ans[i][j]=x++;
j--;
}
while(i>k){
ans[i][j]=x++;
i--;
}
k++;
}
if(n%2==1){
ans[k][k]=x;
}
return ans;
}
}
螺旋矩阵这个题其实想明白了很简单,先按外圈的填,填到最后一个位置前转换填的顺序,先横着填,再竖着填,再从下面右填到左,从下填到上。填完一圈可以填下一圈。
直到填完了,如果n是偶数,就是填完了,如果n是奇数则需要把中间的填上。
数组总结
从二分查找,双指针原地删除,有序数组的平方,螺旋矩阵中可以提炼出的思想是:考虑数组题,在其中遍历,修改,一定要考虑到数组边界和填充方法还有是原地修改还是创建新数组等等。
所以数组问题的工具:二分,双指针,滑动窗口。