算法学习|Day2数组 滑动窗口 螺旋矩阵
今日任务:
数组理论基础,977有序数组的平方. 209长度最小的子数组,59.螺旋矩阵Ⅱ
LeetCode 977 有序数组的平方
解法一: 直接全平方,再排序 (Array.sort(nums))
class Solution {
public int[] sortedSquares(int[] nums) {
for(int i=0;i<nums.length;i++) nums[i]*=nums[i];
Arrays.sort(nums);//java自带排序
return nums;
}
}
解法二: 双指针(左右指针)
比较左右大小,按顺序放入结果数组中(必须开辟新数组空间)
class Solution {
public int[] sortedSquares(int[] nums) {
int left=0,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;
}
}
LeetCode 209 长度最小的子数组
滑动窗口(双指针法)
先在右边进窗口,窗口中和够大了之后,从左边出窗口,保存符合的窗口的最小长度
- 使用快慢指针包住一个区间,根据其中的sum与target比较
- 符合条件就比较最小长度并保存
- 整个过程走完,最终返回最小长度即可
通过不断调整快慢指针的位置,从而得到不同的子序列,子序列中找到最优解
class Solution {
public int minSubArrayLen(int target, 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>=target){
result=Math.min(result,right-left+1);
sum-=nums[left++];
}
}
return result==Integer.MAX_VALUE?0:result;
}
}
LeetCode 59 螺旋矩阵Ⅱ
处理边界问题是难点
边界处理规则上保持一致,比如都是左闭右开区间
- 只需要一圈一圈处理
- 下一圈就更新起始位置
- 注意处理的层数为n/2,如果n为奇数,则需要再给中心位置赋值
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)){
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;
}
}
数组章节总结
数组理论基础
- 数组是存放在连续内存空间的相同数据类型的集合
- 数组下标从0开始,内存地址连续
- 增删操作要移动其他元素
- 多维数组同样是连续地址
数组题型常用思想
-
二分法
-
左闭右开
-
左闭右闭
-
循环不变量/一致原则
双指针法
- 通过两个指针在一个for循环完成两个for的工作
- 快慢指针
- 左右指针
- 因题目情况而定采用不同的双指针
滑动窗口法
- 实质还是快慢指针,指针不回头,不停移动序列位置区间,更新结果集
- 滑动窗口的精妙之处在于根据当前子序列和大小的情况,不断调节子序列的起始位置。从而将O(n^2)的暴力解法降为O(n)
模拟行为
- 根据题意模拟行为
- 关键在于边界条件的处理
- 循环不变量原则,边界处理方式要保持一致性