海智算法训练营第二天 | 第一章 数组part02 | 977有序数组的平方 209长度最小的子数组 59螺旋矩阵II(对撞指针、移动窗口、螺旋矩阵赋值)

本文介绍了如何使用对撞指针解决有序数组的平方问题,移动窗口算法求解长度最小子数组,以及螺旋矩阵的赋值技巧。通过实例展示了这些技术在编程中的实际应用,强化了对算法优化的理解。
摘要由CSDN通过智能技术生成

 学习目标:

1.对撞指针返回每个数字的平方组成的新数组

2.通过移动窗口返回长度最小的子数组

3.学习螺旋矩阵赋值的思想给矩阵螺旋赋值

1.977有序数组的平方

暴力解法就不细琐了,就是用一个循环将数组内所有的数进行平方,最后再进行排序。这样的算法时间复杂度是O(n+logn)

主要使用的是对撞指针(双指针)的解法:

头指针从头开始,尾指针从数组的末尾开始,设置一个index下标指针用于给新数组赋值,因为有序数组平方之后最大的肯定是数组两边的数字,所以只需要对比两个指针的大小就可以有序将新数组赋值了:

题目:有序数组的平方

class Solution {
    public int[] sortedSquares(int[] nums) {
        int l = 0, r= nums.length-1;
        int index = nums.length-1;
        int res[] = new int[nums.length];
        while(l<=r){
            if(nums[l]*nums[l] > nums[r]*nums[r]){
                res[index--] = nums[l]*nums[l];
                l++;
            }else{
                res[index--] = nums[r]*nums[r];
                r--;
            }
        }
        return res;
    }
}

2.209长度最小的子数组

暴力解法就不说了,用两个for循环从头到尾遍历一遍,时间复杂度为O(n^2)

这里用的是移动窗口算法,此算法的精髓就是移动窗口的始末位置,结束位置不断向右,当窗口内的值增大到大于目标值后,起始位置就向右到窗口内的值小于目标值,这样不断直到结束位置到数组末尾,中间不断记录窗口的大小长度。

题目:长度最小的子数组

class Solution {
    public int minSubArrayLen(int target, int[] nums) {
        int l = 0;
        int sum = 0;
        int res = Integer.MAX_VALUE;
        for(int r = 0; r<nums.length;r++){
            sum += nums[r];
            while(sum >=target){
                res = Math.min(res,r-l+1);
                sum -= nums[l++];
            }
        }
        return res == Integer.MAX_VALUE ? 0:res;
    }
}

3.59螺旋矩阵II

螺旋矩阵思想简单,难度在于代码实现需要步骤多。首先需要找一个循环不变量,那就是每次循环不变的是都是从左到右,右到下,下到左,左到上,所以我们可以从这里入手,假设以左闭右开的思想去做,第一行循环到倒数第二个数,最后一列循环从第一行最后一个数开始,然后每次循环都像这样,这就是宗旨思想。

难度在于如何实现:首先循环次数可以用n/2计算出来(每次循环会减少两行两列),再设置x,y来记录起始位置,i,j为当前循环位置。        第一次for循环:i从x开始,直到第一行倒数第二个数,这时候需要设置一个offSet变量来记录每行赋值到倒数第几个数,初始值为1,因为下一次循环就会到第二行倒数第三个数,不断递增,所以offSet变量每次循环都需要+1。        第二次for循环:跟第一次循环类似,但注意此时赋值时是用arr[i][j],因为此时的j已经在上一次循环抵达了当前循环这一圈的最大值。        第三、四次for循环:此时的i,j都不用初始化,已经在上几次的循环被记录了下来,只需要赋值直到他们回到最小值。        最后:判断n是否时奇数,如果是的话,那么只剩矩阵中间还没赋值,那么直接让arr[x][y]=count就行了,因为此时的x,y已经是最后一个中间数的初始位置了。

题目:螺旋矩阵

class Solution {
    public int[][] generateMatrix(int n) {
        int [][] arr = new int[n][n];
        int x = 0, y= 0;//设置起始位置,遵循左闭右开原则
        int loop = n/2;//记录循环次数
        int i,j;
        int offSet = 1;//一行或一列需要几个不赋值
        int count = 1;
        while(loop-->0){//循环几圈,如果是奇数后面进行处理
            for(j =y;j<n-offSet;j++){//左上到右上
                arr[x][j] = count++;
            }
            for(i =x;i<n-offSet;i++){//右上到右下
                arr[i][j] = count++;
            }
            for(;j>y;j--){//右下到左下
                arr[i][j] = count++;
            }
            for(;i>x;i--){//左下到左上
                arr[i][j] = count++;
            }

            offSet++;
            x++;
            y++;
            
        }
        if(n%2 == 1) arr[x][y] = count;
        return arr;
    }
}

总花费时间:3h

总结:这次学习巩固了对撞指针和移动窗口的思想,并且学习到了新思想——如何给矩阵螺旋赋值.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值