代码随想录算法训练营 day 2 | 209.长度最小的子数组,59.螺旋矩阵II,区间和,开发商购买土地

一、长度最小的子数组

209.长度最小的子数组 

代码随想录文章解析

解题思路

采用滑动窗口方法,其实也是双指针法的一种,只不过用滑动窗口能够更为形象地描述这个方法的动态过程。

所谓滑动窗口,就是不断的调节子序列的起始位置和终止位置,从而得出我们要想的结果。

(1)在该题中,i 定为初始位置,j 定为终止位置。首先设置一个for循环。

(2)并在该for循环中,从初始位置开始,先对num[j]依次相加,用sum记录累加和,直至sum>=target值。

(3)然后再用while循环进行如下操作。当sum>=target时,首先记录累加和为sum的子数组长度,然后sum - =num [i],i 向数组下一位移动,即i=i+1。这样就完成了滑动操作。继续这样的操作直至sum<target,此时sum的长度最小。

具体代码如下:

class Solution {
    public int minSubArrayLen(int target, int[] nums) {
        int i=0,result=Integer.MAX_VALUE;
        int sum=0;
        for(int j=0;j<nums.length;j++){
            sum+=nums[j];
            while(sum>=target){
                int currentL=j-i+1;
                result=Math.min(result,currentL);
                sum-=nums[i];
                i++;
            }
        }

//如果result没有被更改过,说明数组中所有值加起来仍然小于target,所以实际返回值应该为0
         return result == Integer.MAX_VALUE ? 0 : result;
    }
}

看到本题我的第一想法是采用双层for循环进行计算,但是for循环中具体怎么实现还是不太清楚,于是看了b站上carl哥的视频讲解。滑动指针的思路确实不太好理解,但是和代码以及数组的动态变化结合到一起就比较容易接受。

二、.螺旋矩阵II

代码随想录文章解析

螺旋矩阵最主要的是边界条件的设置。边界是动态变化的,并且是从外往里螺旋赋值。

loop为圈数,每旋转一圈,loop+1。

x,y为每一圈旋转的初始位置。

由于每次循环赋值时的区间为左闭右开区间,所以设置offset。循环终结条件为n-offset,也就是右边界不赋值。offset初始值为1,每循环一圈,offset+1。

代码如下:

class Solution {
    public int[][] generateMatrix(int n) {
        int i,x=0,y=0,j,loop=1,count=1,offset=1;
        int[][] result=new int[n][n];
        while(loop<=n/2){
            //顶部
            for(j=y;j<n-offset;j++){
                result[x][j]=count++;
            }
            //右部
            for(i=x;i<n-offset;i++){
                result[i][j]=count++;
            }
            //底部
            for(;j>y;j--){
                result[i][j]=count++;
            }
            for(;i>x;i--){
                result[i][j]=count++;
            }
            x++;
            y++;
            offset++;
            loop++;
        }
        if(n%2!=0){
            result[x][y]=count;
        }
        return result;
    }
}

三、区间和

58. 区间和 | 代码随想录

解题思路

建立一个新数组保存每个元素的前缀和,区间和就可以转变为前缀和的差值。具体代码如下:

import java.util.Scanner;

public class Main{
    public static void main (String[] args) {
        Scanner scanner=new Scanner(System.in);
        int n=scanner.nextInt();
        
        //存储输入的值
        int[] vec=new int[n];

        //存储前缀和
        int[] p=new int[n];

        //存储累加和
        int presum=0;
        for(int i=0;i<n;i++){
            vec[i]=scanner.nextInt();
            presum+=vec[i];
            p[i]=presum;
        }

        while(scanner.hasNextInt()){
            int a=scanner.nextInt();
            int b=scanner.nextInt();
            int sum;
            if(a==0)
                sum=p[b];
            else 
                之所以为p[a-1]是因为区间和中包括了vec[a]的值
                sum=p[b]-p[a-1];
            System.out.println(sum);
        }
        scanner.close();
        
    }
}

四、开发商购买土地

44. 开发商购买土地 | 代码随想录

解题思路

根据题目要求可得:

(1)提供整数 n,m建立二维整数数组[n][m]。

(2)将该二维数组用一条竖线或一条横线划分为两部分。

(3)得到每一部分的总价值,然后求这两部分价值相减的值。

根据以上条件可以得知,我们需要找到(3)步骤中的最小值。

代码如下:

import java.util.Scanner;
public class Main{
public static void main (String[] args) {
    /* code */
    Scanner scanner=new scanner(System.in);
    int n=scanner.nextInt();
    int m=scanner.nextInt();
    int sum=0;
    int[][] vec=new int[n][m];
    for(int i=0;i<n;i++){
        for(int j=0;j<m;j++){
            vec[i][j]=scanner.nextInt();
            sum+=vec[i][j];
            }
        }
        
        int[] hor=new int[n];
        for(int i=0;i<n;i++){
            for(int j=0;j<m;j++){
                hor[i]+=vec[i][j];
            }
        }
        int[] ver=new int[m];
        for(int j=0;j<m;j++){
            for(int i=0;i<n;i++){
                ver[j]+=vec[i][j];
            }
        }
        int result=Integer.MAX_VALUE;
        int horizontaCut=0;
        for(int i=0;i<n;i++){
            horizontaCut+=hor[i];
            result=Math.min(result,Math.abs(sum-2*horizontaCut));
        }
        
        int vercalCut=0;
        for(int j=0;j<m;j++){
            vercalCut+=ver[j];
            result=Math.min(result,Math.abs(sum-2*vercalCut));
        }
        System.out.println(result);
        scanner.close();
    }
}

五、今日收获

今天的总体难度有所提升。滑动窗口需要将代码与范例结合理解,螺旋矩阵需要对边界进行严格设置。区间和利用了前缀和相减完成了求值,最后一题则是在区间和的基础上进行拓展。在看到这些题目时,我有思路,但是并不清晰,或者有关于边界条件的设置总是不够严谨,在看了carl哥的文章与视频后,思路清晰,能够跟着carl哥完成代码的编写,但是有些地方还是不能够准确无误的写下来,因此还需要多学多练多理解。

今日 学习+解题+博客共3h30min。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值