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

文章介绍了LeetCode的几道经典题目,包括使用双指针法解决有序数组的平方问题,以及运用滑动窗口找到长度最小的有序子数组。同时,文章还探讨了如何用二分法生成螺旋矩阵,重点讨论了解题策略和时间复杂度分析。
摘要由CSDN通过智能技术生成

977. 有序数组

参考文章:

参考视频:

解题思路:

解法1:暴力解法,第一步将数组内元素遍历平方,第二步将数组内元素排序。
for(int i=0;i<nums.length;i++){
            nums[i]*=nums[i];
        }
        Arrays.sort(nums);

        return nums;

时间复杂度:O(n + nlog n)

解法2:双指针解法,左指针指向数组第一个元素,右指针指向数组最后一个元素,由于是升序排序,所以元素平方后较大的数会在数组的两头,通过左右指针指向的元素平方进行比较,平方后较大的元素从后往前存入创建的新数组中。

int left=0,right=nums.length-1;
        int[] result = new int[nums.length];
        int i=nums.length-1;
        while(i>=0){
            if(nums[left]*nums[left]>nums[right]*nums[right]){
                result[i]=nums[left]*nums[left];
                left++;
                i--;
            }else if(nums[right]*nums[right]>=nums[left]*nums[left]){
                result[i]=nums[right]*nums[right];
                right--;
                i--;
            }
        }
        return result;

时间复杂度:O(n)

 209.长度最小的有序数组

参考文章:

参考视频:

 解法1:暴力解法,通过两层for循环来寻找长度最小的子数组,后面力扣更新了数据,暴力解法已经超时了。

时间复杂度:O(n ^2)

解法2:滑动窗口(推荐):

在本题中实现滑动窗口,主要确定如下三点:

  • 窗口内是什么?
  • 如何移动窗口的起始位置?
  • 如何移动窗口的结束位置?

窗口就是 满足其和 ≥ s 的长度最小的 连续 子数组。

窗口的起始位置如何移动:如果当前窗口的值大于s了,窗口就要向前移动了(也就是该缩小了)。

窗口的结束位置如何移动:窗口的结束位置就是遍历数组的指针,也就是for循环里的索引。

解题的关键在于 窗口的起始位置如何移动,如图所示:

leetcode_209

可以发现滑动窗口的精妙之处在于根据当前子序列和大小的情况,不断调节子序列的起始位置。从而将O(n^2)暴力解法降为O(n)。

        int i=0,j=0;
        int min=Integer.MAX_VALUE;
        int sum=0;
        while(j<nums.length){
            sum+=nums[j];
            while(sum>=target){
                min = Math.min(min, j - i + 1);
                sum-=nums[i];
                i++;
            }
            j++;
        }
        return min==Integer.MAX_VALUE?0:min;

时间复杂度: O(n)

   59.螺旋矩阵II

参考文章:

参考视频:

解法:二分法,正确的二分法一定要坚持循环不变量原则,我在这里统一使用左闭右开原则。

图示:

这里每一种颜色,代表一条边,我们遍历的长度,可以看出每一个拐角处的处理规则,拐角处让给新的一条边来继续画。

这也是坚持了每条边左闭右开的原则。

注意对于n为奇数时最后一个元素要做单独处理。

        int[][] nums = new int[n][n];
        int i = 0;
        int k = 1;
        int index = 1;
        int x = 0, y = 0, z = 0;
        while (i < n / 2) {
            x=z;
            y=z;
            for (y = z; y < n - k; y++) {
                nums[x][y] = index++;
            }
            for (x = z; x < n - k; x++) {
                nums[x][y] = index++;
            }
            for (; y > z; y--) {
                nums[x][y] = index++;
            }
            for (; x > z; x--) {
                nums[x][y] = index++;
            }
            z++;
            k++;
            i++;
        }
        if (n % 2 != 0) {
            nums[n / 2][n / 2] = index;
        }
        return nums;
时间复杂度: O(n^2)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值