代码随想录算法训练营第二天| 977.有序数组的平方、209.长度最小的子数组、59.螺旋矩阵II(JAVA)

本文探讨了在有序数组平方、长度最小子数组和螺旋矩阵II问题中,如何运用双指针法、滑动窗口技巧,以及循环不变量的重要性。
摘要由CSDN通过智能技术生成


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很久才发现又踩坑了。分析问题掌控代码的能力还是要多刷题多练啊。
不积跬步无以至千里,加油!

  • 14
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值