代码随想录算法训练营第二天|977.有序数组的平方 ,209.长度最小的子数组 ,59.螺旋矩阵II ,总结
977.有序数组的平方
相应的题
题目
给你一个按 非递减顺序 排序的整数数组 nums,返回 每个数字的平方 组成的新数组,要求也按 非递减顺序 排序。
示例 1:
输入:nums = [-4,-1,0,3,10]
输出:[0,1,9,16,100]
解释:平方后,数组变为 [16,1,0,9,100]
排序后,数组变为 [0,1,9,16,100]
示例 2:
输入:nums = [-7,-3,2,3,11]
输出:[4,9,9,49,121]
提示:
1 <= nums.length <= 104
-104 <= nums[i] <= 104
nums 已按 非递减顺序 排序
当时的解法与想法
一开始错误的解法
class Solution {
public int[] sortedSquares(int[] nums) {
for(int i=0;i<nums.length;i++){
nums[i]=nums[i]*nums[i];
}
int left=0;
int save=0;
for(int right=nums.length-1;right>0;right--){
if(nums[right]<nums[left]){
save=nums[right];
nums[right]=nums[left];
nums[left]=save;
}
}
return nums;
}
}
这个是错误的求法,只能求特定的解法很多不具有普遍性
之后改进的做法and想法
class Solution {
public int[] sortedSquares(int[] nums) {
int[] result = new int[nums.length];
int left=0;
int right=nums.length-1;
int j=nums.length-1;
for(int i=0;i<nums.length;i++){
if(nums[left]*nums[left]<nums[right]*nums[right]){
result[j]=nums[right]*nums[right];
j--;
right--;
}else{
result[j]=nums[left]*nums[left];
j--;
left++;
}
}
return result;
}
}
通过在原数组设立左右指针来进行对平方的判定,因为这道题目的特殊性,已经进行了大小的排序。左右两边必定有一个最大的,所以要对左右进行设立指针。重在观察数组之间的内部规律。
![具体的内部运动](https://img-blog.csdnimg.cn/b141194b9cfd457d85e305de8f529f07.gif#pic_center
59.螺旋矩阵II
相应的题
题目
给你一个正整数 n ,生成一个包含 1 到 n2 所有元素,且元素按顺时针顺序螺旋排列的 n x n 正方形矩阵 matrix 。
示例 1:
输入:n = 3
输出:[[1,2,3],[8,9,4],[7,6,5]]
示例 2:
输入:n = 1
输出:[[1]]
提示:
1 <= n <= 20
通过次数287,990提交次数389,496
做法and想法
并没有自己的代码 因为并没有相应的思路,就很懵逼吧
class Solution {
public int[][] generateMatrix(int n) {
int[][] result=new int[n][n];
int start=0;//每一轮循环的初始位置
int x;//x轴的具体数值
int y;//y轴的具体数值
int rou=0;//循环次数
int pri=1;//螺旋上每次递增的数值
while(rou++ < n / 2){//
for(x=start;x<n-rou;x++){//上半部分的从左往右
result[start][x]=pri;
pri++;
}
for(y=start;y<n-rou;y++){//右边部分的从上往下
result[y][x]=pri;
pri++;
}
for(;x>=rou;x--){//下半部分的从右往左
result[y][x]=pri;
pri++;
}
for(;y>=rou;y--){//左边部分的从下往上
result[y][x]=pri;
pri++;
}
start++;
}
if(n % 2 == 1){//如果n为奇数的时候,会多出来一个pri数值
result[start][start] = pri;
}
return result;
}
}
这个要理解好左闭右开等区间的划分我这部分理解,但是还是没有想到这个是今天最难的一题,也是花费时间最长的一题。不仅要理解好循环不变量,还要理解好数组对应的数值的摆放位置。我就是没有搞懂这个
209.长度最小的子数组
相应的题
题目
给定一个含有 n 个正整数的数组和一个正整数 target 。
找出该数组中满足其和 ≥ target 的长度最小的 连续子数组 [numsl, numsl+1, …, numsr-1, numsr] ,并返回其长度。如果不存在符合条件的子数组,返回 0 。
示例 1:
输入:target = 7, nums = [2,3,1,2,4,3]
输出:2
解释:子数组 [4,3] 是该条件下的长度最小的子数组。
示例 2:
输入:target = 4, nums = [1,4,4]
输出:1
示例 3:
输入:target = 11, nums = [1,1,1,1,1,1,1,1]
输出:0
提示:
1 <= target <= 109
1 <= nums.length <= 105
1 <= nums[i] <= 105
做法and改进
class Solution {
public int minSubArrayLen(int target, int[] nums) {
int start=0;
int sum=0;
int result = Integer.MAX_VALUE;//这个数值很大
int j=0;
int a=0;
for(int i=0;i<nums.length;i++){
sum=sum+nums[i];
while(sum>=target){
a=i-j+1;
result=Math.min(result,a);
sum=sum-nums[j];
j++;
}
}
if(result!=Integer.MAX_VALUE){
return result;
}
return 0;
}
}
一开始想用数组来存储长度,但是一直没有解出来。后面看了解析才改成这个。用数值
Integer.MAX_VALUE来搞个最大值来进行比较。对于我来说比数组简单,可能是因为我菜比
总结
二分法
思路很简单,但是通过率在简单题里并不高。
循环不变量原则是这个题目的核心,要考虑区间的不变才能下手
双指针法
通过一个快指针和慢指针在一个for循环下完成两个for循环的工作。
因为数组在内存中都是顺序的,删除的话要全部删掉,所以要用到覆盖的思路。
双指针既可以同向也可反向,要看题目的情况具体分析有一说一我一般下意识都是同向,导致有时候会莫名其妙卡住
滑动窗口
本质上是双指针法的特殊形式是因为他的动画效果和滑窗差不多才取名这个。
这个的精妙之处在于根据当前子序列和大小的情况,不断调节子序列的起始位置。从而将O(n^2)的暴力解法降为O(n)。