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]
解题思路
最简单的方法就是直接平方完然后排个序,当然时间开销很大。
由于最大的数一定会从数组的两边取到,所以可以用双指针法,从两边依次往里遍历,就可以在一个循环里完成,不需要额外排序。
代码
//暴力
import java.util.Arrays;
class Solution {
public int[] sortedSquares(int[] nums) {
int i=0;
int[] newNums = nums;
for(i=0; i<nums.length; i++){
newNums[i]=nums[i]*nums[i];
}
Arrays.sort(newNums);
return newNums;
}
}
时间复杂度:O(n+nlogn)
//双指针
import java.util.Arrays;
class Solution {
public int[] sortedSquares(int[] nums) {
int left=0, right=nums.length-1;
int[] newNums = new int[nums.length];
for(int n=nums.length-1; n>=0; n--){
int l=nums[left]*nums[left];
int r=nums[right]*nums[right];
if(l>r){
newNums[n]=l;
left++;
}
else{
newNums[n]=r;
right--;
}
}
return newNums;
}
}
时间复杂度:O(n)
209.长度最小的子数组
给定一个含有 n 个正整数的数组和一个正整数 s ,找出该数组中满足其和 ≥ s 的长度最小的 连续 子数组,并返回其长度。如果不存在符合条件的子数组,返回 0。
示例:
- 输入:target = 7, nums = [2,3,1,2,4,3]
- 输出:2
解释:子数组 [4,3] 是该条件下的长度最小的子数组。
提示:
- 1 <= target <= 10^9
- 1 <= nums.length <= 10^5
- 1 <= nums[i] <= 10^5
解题思路
力扣更新之后此题用暴力方法解会报超时,本题主要还是用滑动窗口法,在我看来与双指针法有些神似。
设置左右两个指针分别划定子数组的开始和结束。移动右指针直到大于target时移动左指针缩小数组长度。
精髓在于控制左指针(子数组开始指针)的移动来缩小子数组长度。
代码
//暴力
class Solution {
public int minSubArrayLen(int target, int[] nums) {
int n = 0;
int result=nums.length, sum=0;
for(int i=0; i<nums.length; i++){
n=0;
sum=0;
for(int j=i; j<nums.length; j++){
if(n<target){
n += nums[j];
sum++;
}
else{
break;
}
}
if(n>=target && sum<result){
result=sum;
}
else if(i==0 && n<target){
return 0;
}
}
return result;
}
}
时间复杂度:O(n²)
//滑动窗口
class Solution {
public int minSubArrayLen(int target, int[] nums) {
int left=0, right=0;
int n=0, result=Integer.MAX_VALUE;
for(right=0; right<nums.length; right++){
n+=nums[right];
while(n>=target){
result = Math.min(result, right - left + 1);
n -= nums[left++];
}
}
return result == Integer.MAX_VALUE ? 0 : result;
}
}
时间复杂度:O(n)
注意:不是for里面一个while一定是O(n²),这个解法中左右指针都只遍历数组一次,时间复杂度为O(2*n)
59.螺旋矩阵II
给你一个正整数 n ,生成一个包含 1 到 n2 所有元素,且元素按顺时针顺序螺旋排列的 n x n 正方形矩阵
示例1:
- 输入:n = 3
- 输出:[[1,2,3],[8,9,4],[7,6,5]]
解题思路
没什么取巧的解法,重点在于判断拐弯时候的边界条件,确定左闭右开或左开右闭就四条边都用同一种方式解。
类似二分法的思想(但是更难一点),关键是确定好循环不变量
代码
代码如下(示例):
class Solution {
public int[][] generateMatrix(int n) {
int x, y,;
//每次循环开始的位置
int startx=0, starty=0;
//为矩阵赋值
int count=1;
// 每个圈循环几次,例如n为奇数3,那么loop = 1 只是循环一圈,矩阵中间的值需要单独处理
int loop=n/2;
// 控制遍历边界,每次循环减1
int set = 1;
int[][] res=new int[n][n];
while(loop-- > 0){
x=startx;
y=starty;
for(;y<n-set;y++){
res[x][y]=count++;
}
for(;x<n-set;x++){
res[x][y]=count++;
}
for(;y>starty;y--){
res[x][y]=count++;
}
for(;x>startx;x--){
res[x][y]=count++;
}
startx++;
starty++;
set++;
}
//假如是奇数的话,最中间的位置不会被遍历到,需要单独赋值
//如n=时,res[2][2]=9需要单独赋值
int mid=n/2;
if (n % 2==1) {
res[mid][mid] = count;
}
return res;
}
}
时间复杂度O(n²)
总结
数组算是结束了,双指针法和滑动窗口法掌握的还算可以,循环不变量的思想虽然大概有点概念了但换题还是会先debug很久才发现又踩坑了。分析问题掌控代码的能力还是要多刷题多练啊。
不积跬步无以至千里,加油!