自学内容网 自学内容网

代码随想录day2| 209.长度最小的子数组、 59.螺旋矩阵II、区间和、开发商购买土地

209.长度最小的子数组

知识点

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

  • 寻找子数组使用滑动窗口可以将O(n^2)的复杂度降到O(n)

步骤

  • 定义快慢指针s、f (寻找子数组)
  • 由于题目只需要返回最小数组的长度,而不是具体的数组,所以只需要一个min来记录最小长度,用cnt来记录当前窗口中数的和。
  • 用for循环遍历f,来操作f,f每次加一都要更新cnt的值;
    • 当cnt>=target时,用while循环来操作s指针,s每次加一,更新cnt的值
    • 直到cnt<target,移动f(快指针),以此增加cnt的值

总结

(窗口中)数组和大了移动慢指针,数组和小了移动快指针,以此方法来寻找所有满足条件的子数组,并在这个过程中记录每个子数组的长度,更新在最小值min中,最后返回即可。

class Solution {
    public int minSubArrayLen(int target, int[] nums) {
        int s = 0;
        int f = 0;
        int cnt = 0;
        int min = -1;
        for( ; f < nums.length ; f++){
            cnt+=nums[f];
            while(cnt>=target){
                if(min == -1){
                    min = f-s+1;
                }
                min = f-s+1 < min?(f-s+1):min;
                cnt -= nums[s++];
            }

        }
        return min == -1?0:min;
    }
}

代码优化

class Solution {

    // 滑动窗口
    public int minSubArrayLen(int target, int[] nums) {
        int s= 0;
        int cnt= 0;
        int min= Integer.MAX_VALUE;
        for (int f= 0; f< nums.length; f++) {
            cnt+= nums[f];
            while (cnt>= target) {
                min= Math.min(min, right - left + 1);
                cnt-= nums[s++];
            }
        }
        return min== Integer.MAX_VALUE ? 0 : min;
    }
}

59.螺旋矩阵II

步骤

  • 首先想清楚一圈循环这么操作,这里我采用循环不变量:左开右闭,定义四个for循环操作 和 i,j,指针。
  • 一圈的逻辑串通以后,再在四个for循环外层加入while循环,控制要转几圈。
  • 转几圈需要考虑n(新数组的宽高)的大小,奇数和偶数两种情况,找出while循环条件为n>1,每次循环结束n-=2;
  • 随着每圈的变化(while循环),每圈的起始位置和终止位置都有所变化,单独抽出两个变量start ,end 来控制
  • 最后判断n为奇数时最后会有中心一个空位置,填上即可。
    请添加图片描述
class Solution {
    public int[][] generateMatrix(int n) {
        int j = 0;
        int i = 0;
        int num = 0;
        int start = 0;
        int end = n-1;
        int[][] matrix =  new int[n][n];
        while(n>1){
            for(;j<end;j++){
                matrix[i][j] = ++num; 
            }
            for(;i<end;i++){
                matrix[i][j] = ++num; 
            }
            for(;j>start;j--){
                matrix[i][j] = ++num; 
            }
            for(;i>start;i--){
                
                matrix[i][j] = ++num; 
                if(i == 1 && j == 0){
                    System.out.print("| " +matrix[i][j] + " | ");
                }
            }
            i++;
            j++;
            start++;
            end--;
            //start,end不能和n共用,要分开控制!!
            n-=2;
        }
        if(n == 1){
            matrix[i][j] = ++num; 
        }
        return matrix;
    }
}

区间和

知识点

  • 暴力解法的时间复杂度是 O(n * m) m ,使用前缀和,重复利用计算过的子数组之和,从而降低区间查询需要累加计算的次数。
  • 具体思路

代码实现

import java.util.Scanner;
public class Main{
    
    public static void main(String[] args ){
        Scanner scanner = new Scanner(System.in);
        int n = scanner.nextInt();
        int[] arr = new int[n];
        int cnt = 0;
        
        for(int i = 0 ; i < n ; i++){
            cnt+=scanner.nextInt();
            arr[i] = cnt;
            
        }
        while(scanner.hasNextInt()){
            int i = scanner.nextInt();
            int j = scanner.nextInt();
            int sum;
            if (i == 0) {
                sum = arr[j];
            } else {
                sum = arr[j] - arr[i - 1];
            }
            System.out.println(sum);
        }
    }
    
}

开发商购买土地

这道题也是使用的前缀和:具体思路

import java.util.Scanner;
public class Main{
    public static void main(String[] args){
        Scanner scanner = new Scanner(System.in);
        int n = scanner.nextInt();
        int m = scanner.nextInt();
        int[][] vec = new int[n][m];
        int cnt = 0;
        for(int i = 0 ; i <n ; i++){
            for(int j = 0 ; j <m ; j++){
                vec[i][j] = scanner.nextInt();
                cnt += vec[i][j];
            }
        }
        
        int[] vecx = new int[n];
        
        for(int i = 0 ; i <n ; i++){
            int sum = 0;
            for(int j = 0 ; j <m ; j++){
                sum += vec[i][j];
            }
            vecx[i] = sum;
        }
        
        int[] vecy = new int[m];
        for(int j = 0 ; j <m ; j++){
            int sum = 0;
            for(int i = 0 ; i < n ; i++){
                sum += vec[i][j];
            }
            vecy[j] = sum;
        }
        int min =  Integer.MAX_VALUE;
        int sumy = 0;
        for(int i = 0 ; i<m-1;i++){
            sumy+=vecy[i];
            int dif = Math.abs(cnt-2*sumy);
            min = dif<min?dif:min;
        }
        int sumx = 0;
        for(int i = 0 ; i<n-1;i++){
            sumx+=vecx[i];
            int dif = Math.abs(cnt-2*sumx);
            min = dif < min ? dif : min;
        }
        System.out.print(min);
        
        
    }
}

总结反思

  • 模拟题目先想清楚思路,写出伪代码,再慢慢调试代码,看写出的代码是不是之前想的思路

原文地址:https://blog.csdn.net/m0_68516464/article/details/143000782

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!