今日主要题目
主要学习网址
做题思路与具体代码
题目一 977.有序数组的平方
做题思路
本题采用双指针的做法
1.左右两个指针分别在数组的最左侧和最右侧开始移动
2.定义一个新数组存放结果集
3.该数组是从小到大,所以最左侧和最右侧的平方才是最大的,所以要从新数组的最左边插入
4.比较左右指针所在位置的值的平方,大的那边就先放入结果数组的最右边
(等于其实放哪个都可以,移动哪个也都可以)
5.放入结果数组后,需要将该指针向中间靠拢,结果数组的指针也得向左走
6.循环是左指针小于等于右指针
具体代码
class Solution {
public int[] sortedSquares(int[] nums) {
// 初始化左右指针
int i=0;
int j=nums.length-1;
// 初始化结果数组
int[] result =new int[nums.length];
// 初始化结果指针
int k=nums.length-1;
// 左右指针向中间靠拢
while(i<=j){
if(nums[i]*nums[i]<nums[j]*nums[j]){
// 右边指针所在位置的值的平方大于左边指针所在位置的值的平方
// j指针所在位置平方放在结果指针所在位置,j指针移动,结果指针移动
result[k]=nums[j]*nums[j];
k--;
j--;
}
//其他条件
// 两种情况:
// 1.右边指针所在位置的值的平方小于左边指针所在位置的值的平方
// 2.右边指针所在位置的值的平方等于左边指针所在位置的值的平方
// 一样解决方法
else{
// i指针所在位置平方放在结果指针所在位置,i指针移动,结果指针移动
result[k]=nums[i]*nums[i];
k--;
i++;
}
}
return result;
}
}
题目二 209.长度最小的子数组
做题思路
本题思路类似双指针+前缀和
可以用暴力,但是超时,这里不做展示
1.定义起点指针和结束指针
2.结束指针不断往前走,直到结束指针与起点指针之间值的和大于目标值
3.此时结束指针不懂,在while循环中起点指针不断接近结束指针,找到满足条件,但是区间段的长度最小,找到最小的那个值
4.直到区间段的和又重新小于目标值,跳出循环,
注意事项:
其中的结果要初始化为数组的最大值,有利于做判断
具体代码
class Solution {
public int minSubArrayLen(int target, int[] nums) {
// 初始化起点指针和终点指针
int i=0;
int j=0;
//初始化终点指针与起点指针之间区间的和
int sum=0;
// 初始化返回结果
// 设置为数组最大值
int result=Integer.MAX_VALUE;
// 终点指针不断向右走
for(;j<=nums.length-1;j++){
// 终点指针与起点指针之间值的和
sum+=nums[j];
// 当和大于等于目标值时,就开始将起点指针不断向右移动缩小,知道找到满足条件的最小的区间长度
// j-i+1就是这个区间长度
while(sum>=target){
result=Math.min(result,j-i+1);
sum-=nums[i];
i++;
}
}
//要是结果还是最大值的话,就证明没有满足条件的,就直接返回0
return result == Integer.MAX_VALUE ? 0 : result;
}
}
题目三 59.螺旋矩阵
本题思路
本题思路采用循环,主要思路包括左闭右开,4个流程比如:
从左往右、从上往下、从右往左、从下往上
按照顺序不断循环(顺序很重要)
1.首先初始化循环的圈数从0开始(为了后面这个写法while(loop++<n/2)做准备)
2.初始化不断改变位置的i和j
3.定义循环的开始点和用来填充新数组的数字count
4.记住得定义新的二维数组
5.从左往右:
这时候需要初始化j=start,因为start会根据圈数不同而改变
j到运行到n-loop的位置,随着圈数的增加,j运行的范围就越来越小
再把值不断赋给新的二维数组
6,从上往下:
这时候j就不用变了,但是i需要初始化为start,因为start会根据圈数不同而改变
i同样运行到n-loop的位置,随着圈数的增加,i运行的范围就越来越小
7.从右往左:
这时候i和j的值都不需要初始化了,在原有基础上修改就好,i不变,j不断向左走
走到loop的位置(我们一开始初始化走的位置是0,loop现在是1,还是符合左闭右开的原则的)
8.从下往上
这时候i和j的值都不需要初始化了,在原有基础上修改就好,j不变,i不断向上走
走到loop的位置(我们一开始初始化走的位置是0,loop现在是1,还是符合左闭右开的原则的)
(边界问题要处理好)
9.走完一圈了,start得加1,就是新的一圈起始位置加1了,新的起始位置是(1,1)不再是(0,0)
起始位置也就是这个循环圈的头
10.最后最后注意一个问题,我们默认旋转的圈数是n/2圈,但是如果是奇数圈,中间就会多出一个中间点,所以要加上去res[start][start]=count++;
此时start就是最后这个点圈的起始点也是唯一点
11.返回结果二维数组
具体代码
class Solution {
public int[][] generateMatrix(int n) {
//初始化已经循环的圈数,从0开始
//为什么是从0开始,因为后面用到了loop++<n/2
int loop=0;
//从左往右
//从上往下
//从右往左
//从下往上
//定义循环的开始点(start,start)=(0,0)
int start=0;
//初始化返回数组
int res[][]=new int[n][n];
//初始化填充数字
int count=1;
//初始化循环用到的i,j
int i,j;
//按圈数循环
//这里loop++简化了开发,不用一直在后面写上loop++,但是有个问题,loop初始值需要为0
while(loop++<n/2){
//从左往右
//x为初始位置,y为j向右移动,遵循左闭右开的原则,直到到达边界n-loop
for(j=start;j<n-loop;j++){
res[start][j]=count++;
}
//从上往下
//y为j已经移动到的位置,x为i向下移动
for(i=start;i<n-loop;i++){
res[i][j]=count++;
}
//从右往左
//此时不必初始化值因为,i和j都已经初始化了并且走了一些距离了
//y为j向左走,走到loop位置,loop位置代表圈数比如1,可以走到1
for(;j>=loop;j--){
res[i][j]=count++;
}
//从下往上
//x为i向上走,走到loop位置,loop位置代表圈数比如1,可以走到1
for(;i>=loop;i--){
res[i][j]=count++;
}
//走完一圈了,初始值位置改变
start++;
}
//因为转一圈遍历的是两行,所以要除2
//如果是奇数的话,多出一个中间点
if(n%2==1){
res[start][start]=count++;
}
return res;
}
}