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

977.有序数组的平方

这道题给出的原数组有两个特点:
1、由小到大
2、有负数有正数
因此,这个数组平方后的数应该是从两头向中间的0减小的,但是两头的大小需要我们用两个指针便历之后去判断大小。在遍历的同时left指针向右走,right指针向左走,每次判断left和right指针指向的平方数的大小,哪边大就将这个大的数放到新的数组中,注意:题目要求新数组由小到大排列,所以我们也要由最后往前面放平方数。 每次判断大小,如果是left指针的平方数大,left右移一位;如果是right指针的平方数大,right左移一位,直到right=left,为什么要等于?因为当right=left的时候,它们同时指向的这个平方数还没有被放到新数组里,因此要判断一次大小(当然是一样大的)再将这个数放到新的数组中。
可以举一个很简单的例子: 当原数组只有两个元素的时候,left=0,right=1,两个指针判断玩大小只会把一个指针指向的平方数放到新数组中,还有一个还没放,因此还需要再移动一下指针,再放一次。

class Solution {
    public int[] sortedSquares(int[] nums) {
        int left = 0;
        int right = nums.length - 1;
        int[] numsRes = new int[nums.length];
        int i = nums.length - 1;//这个i用来控制放入新数组的位置,无论是左右指针哪一个更新,i都需要--
        while(left <= right){//注意这里的等于也是有含义的,假设整个数组就两个数,那么left = right,也需要进行一次while循环
            if(nums[left]*nums[left] >= nums[right]*nums[right]){
                numsRes[i] = nums[left]*nums[left];
                i--;
                left++;
            }else{
                numsRes[i] = nums[right]*nums[right];
                i--;
                right--;
            }
        }
        return numsRes;
    }
}

59.螺旋矩阵||

在这里插入图片描述

这道题目根据题意,需要创建一个int[n][n]的数组,然后按照题目顺时针的顺序将[1,n**2]的数字放到这个数组中,所以关键在于确定每个数放置的位置的索引值,以控制数是顺时针放置在数组中的。
如图所示,我们放置的整体顺序是一圈一圈的,每个圈四个边,每个边有起始位置用start参数控制,每一圈中每个边遍历的个数不同,因此用offset控制,offset如图所示往里一圈+2,start如图所示往里一圈+1。
一共应该是(int)n/2圈,如果n是奇数的话最中间的是单独的一个元素,需要单独给值,我们最后判断一下n就行了,赋个值。

class Solution {
    public int[][] generateMatrix(int n) {
        int[][] res = new int[n][n];//存储结果数组
        int offset = 1;//控制不同圈每个边遍历的个数
        int start = 0;//控制不同圈每个边起始索引
        int num = 1;//控制要放入的值
        for(int i = 0;i < n/2;i++){//圈数
            for(int k = 0;k < n-offset;k++){//上边
                res[start][k+start] = num;
                //如图上边的x不变为start,y从start往后共遍历n-offset个元素
                num++;
            }
            for(int k = 0;k < n-offset;k++){//右边
                res[start+k][n-1-start] = num;
                //如图右边的y不变为n-1-start,x从start往后共遍历n-offset个
                num++;
            }
            for(int k = 0;k < n-offset;k++){//下边
                res[n-1-start][n-1-start-k] = num;
                //如图下边的x不变为n-1-start,y从n-1-start开始往前共遍历n-offset个,因此为减
                num++;
            }
            for(int k = 0;k < n-offset;k++){//左边
                res[n-1-start-k][start] = num;
                //如图左边的y不变为start,x从n-1-start开始往前遍历共遍历n-offset个,因此为减
                num++;
            }
            start++;//遍历完一圈start加一
            offset+=2;//遍历完一圈offset加2
        }
        if(n%2 == 1) res[n/2][n/2] = n*n;//n偶数的话正好遍历n/2圈,n为奇数的话最中间的这个元素需要单独赋值
        return res;
    }
}

209.长度最小的子数组

暴力解法

当然超出了时间限制,这里讲解一下思路:
定义两个指针left和right,初始化为0。left标定之后,right向后遍历,只要left或者right指针动一次,就计算[left,right]区间里的和sum。
如果sum>=target,left++以减少sum;
如果sum<target,right++以增加sum;
while()循环用right<nums.length条件控制,left永远小于right。
最后如果left0并且rightlength,说明整个数组的和都达不到target,返回0.

class Solution {
    public int minSubArrayLen(int target, int[] nums) {
        int left = 0;
        int right = 0;
        int res = nums.length;
        while(right < nums.length){
            int sum = 0;
            for(int i = left;i <= right;i++){
                sum += nums[i];
            }
            if(sum >= target){
                res = Math.min(res,right-left+1);
                left++;
            }else{
                right++;
            }
        }
        if(left == 0 && right == nums.length) return 0;
        return res;
    }
}

209.滑动窗口

这个方法需要两个指针i和j控制滑动窗口的头和尾,尾指针需要遍历整个数组,i指针用来当j指针滑动到符合条件的区间的尾的时候,调整区间的头从而缩小滑动窗口的区间以获得最小的区间。

class Solution {
    public int minSubArrayLen(int target, int[] nums) {
        int sum = 0;
        int i = 0;
        int res = nums.length;
        int total = 0;
        for(int j = 0;j < nums.length;j++){
            total += nums[j];
            sum+=nums[j];
            while(sum >= target){//当遇到符合条件的区间的时候,需要去持续缩小该区间的范围直到找到最短的符合条件的区间,所以这里用while不用if
                res = Math.min(res,j-i+1);//每次缩小范围之后去获取一下这个最小范围的区间长度
                sum -= nums[i];//sum减去缩小的nums[i]的值
                i++;//头指针右移
            }
        }
        if(total < target) return 0;//在遍历的过程中,也同时获取到了整个数组的和,如果整个数组的和都小于target了,则说明该数组不存在满足条件的子数组,因此返回0.
        return res;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值