代码随想录训练营第二天

本文分享了解决LeetCode题目977有序数组平方、209长度最小子数组和59螺旋矩阵II的方法,重点讲解了双指针策略、滑动窗口的应用以及螺旋矩阵的填充逻辑,提升对算法的理解和实战能力。
摘要由CSDN通过智能技术生成

代码随想录训练营第二天

leetcode 977.有序数组的平方 209.长度最小的子数组 59.螺旋矩阵II

977.有序数组的平方
977有序数组的平方

看到题的思路

初看到这道题的时候,想到排序也可以做。但是不用排序应该怎么做。
首先初始的数组是从小到大排序的。有正数也有负数。负数的平方会大于正数的平方,这取决于绝对值的大小。
那么怎么保证平方后数组仍能从小到大排序呢
这时候想到两个指针,头尾各一个。平方后比较大小。
创建一个ans数组装平方排序后的数值。大的值放到数组的后面。从后到前填充数组。同时指针变动。小的那个指针不变。
这样扫一圈就可以得到最终的答案。同时也要注意循环停止条件。

代码


class Solution {
    public int[] sortedSquares(int[] nums) {
        int len=nums.length;
        int []ans=new int[len];
        int k=len-1;
        for(int i=0,j=len-1;i<=j;)
        {
            if(Math.pow(nums[i],2)>=Math.pow(nums[j],2))
            {
                ans[k]=(int)Math.pow(nums[i],2);
                i++;
            }
            else
            {
                ans[k]=(int)Math.pow(nums[j],2);
                j--;
            }
            k--;
        }
        return ans;

    }
}

209.长度最小的子数组
209 长度最小的子数组

看到题的思路

看到这题,首先的想法就是暴力。o(n^2)。但是这种会超时。
那么怎么才能简单的找到最小子数组呢?
后来想到前置和:[2,3,1,2,4,3] 的前置和数组就是[0,2,5,6,8,12,15]。
前置和代表着前n位的数值之和。前面添0是为了方便算相邻子数组的个数。比如12-5=7=target 12的index=5,5的index=2;相减等于3。也就是3个子数组的和 。即1,2,4的和。
然后用快慢指针,快指针对应的值减去慢指针对应的值,大于target就是满足题意。记录此时快慢指针之间的距离。更新最小距离。如果一直大的话。就不断地更新慢指针,直到相减小于target。

class Solution {
    public int minSubArrayLen(int target, int[] nums) {
        int len=nums.length;
        int[] ans=new int[len+1];
        ans[0] =0;
       for(int i=1;i<=len;i++)
       {
        ans[i]=ans[i-1]+nums[i-1];//前置和
       }
       int min=Integer.MAX_VALUE;
       
       for(int i=0,j=0;j<=len;)
       {

            while(ans[j]-ans[i]>=target)//大于target时候不断更新慢指针
            {
               
                min=Math.min(j-i,min);
                i++;

            }        
            j++;
       }
       return min==Integer.MAX_VALUE?0:min;

    }
}

不过这道题题解是用的滑动窗口。利用i j快慢两个指针不断调整窗口的区间。
i是慢指针,j是快指针
什么时候需要调整指针位置呢?
i先不移动。j不断移动直到i到j区间的和>=target。记录指针间距,更新最小子区间长度。
但是此时我们没办法保证当前j为尾时该区间长度最小。现在i应该向前走一步。我们需要判断i+1这个位置到j的和是不是也大于target?如果是的话,那继续更新最小子区间长度。直到j到i这中间的和小于target为止。
下一次就是快指针j再向前走一步。判断此时i到j的是否大于等于target。重复以上环节…

代码

class Solution {
    public int minSubArrayLen(int target, int[] nums) {
        int n=nums.length;
        if(n==0)
        {
            return 0;
        }
        int ans=Integer.MAX_VALUE;
        int start=0,end=0;
        int sum=0;
        while(end<n)
        {
            sum+=nums[end];
            while(sum>=target)
            {
                ans=Math.min(end-start+1,ans);
                sum-=nums[start];
                start++;
            }
            end++;
        }
        return ans==Integer.MAX_VALUE?0:ans;
        
    }
}

59.螺旋矩阵II
59 螺旋矩阵Ⅱ

看到题的思路

这个题真的就是要先理清思路,该从哪里下手。
我们要先确定我们应该怎么将1~n*n这些数字填充到二维数组中。
既然他是螺旋分布,那我们就得螺旋着去填充。每螺旋一层为一次循环。我们需要几次循环。答案是n/2;对于奇数来说最终中间会剩一个。那我们就直接在最后处理这个数就行。
每次螺旋转一圈,有四条边。我们需要处理好四个角也就是边界区域。
拿n=4来说。在最外一圈 我们是每次填充123还是1234。这四条边应该有同一的规则所以我们应该是先123 然后456 然后 789 最后10 11 12 也就是相当于是左闭右开。头闭尾开

代码

class Solution {
    public int[][] generateMatrix(int n) {
        int startx=0;
        int starty=0;
        int offset=1;
        int count=1;
        int[][]a=new int[n][n];
        int time=n/2;
        int j=0,i=0;
        while(time!=0)
        {
            for( j=starty;j<n-offset;j++)
                a[startx][j]=count++;
            for(i=startx;i<n-offset;i++)
                a[i][n-offset]=count++;
            for(;j>startx;j--)
                a[n-offset][j]=count++;
            for(;i>starty;i--)
                a[i][startx]=count++;
            offset++;
            startx++;
            starty++;
            time--;
        }
        if(n%2!=0)
        {
            a[n/2][n/2]=n*n;
        }
    return a;

    }
}

今日收获
今天的题目比昨天的难了!通过这几道题加深了双指针的理解,能够更好的应用在题目当中。还学会了滑动窗口,动态的解决问题。螺旋矩阵这个题虽然没涉及到别的算法知识,但是要理清思路,注意条件。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值