第一章 数组Part2

209.长度最小的子串

思路:

使用滑动窗口,i指向长度最小子数组的开始位置,j指向长度最小子数组的结束位置。
j先右移,当子数组和大于target时,j停止移动,i右移,直到子数组和小于target。

class Solution {
    public int minSubArrayLen(int target, int[] nums) {
        //滑动窗口 
        //i指向长度最小子数组的开始位置,j指向长度最小子数组的结束位置
        //j先右移,当子数组和大于target时,j停止移动,i右移,直到子数组和小于target
        int i = 0, j = 0;
        int sum = 0, sumLength = Integer.MAX_VALUE;
        for(j = 0; j < nums.length; j++){
            sum += nums[j];
            while(sum >= target){
		//左右边界异动后都要更新长度
                sumLength = (j - i + 1) < sumLength ? (j - i + 1) : sumLength;
                sum -= nums[i++];
            }
        }
        return sumLength == Integer.MAX_VALUE ? 0 : sumLength; 
    }
}

反思:

1.对循环条件的考虑不到位。看了思路后自己先写,两层循环写了外层循环控制开始位置。
2.子数组长度的更新在循环外。每次边界变化后子数组的长度都应该随之变化。


59.螺旋矩阵Ⅱ

思路:

先写出最外面一圈,然后找到控制移动的变量。
使用左闭右开的原则,从左到右-从上到下-从右到左-从下到上。
一圈结束后,下标缩小,start++,end--.

class Solution {
    public int[][] generateMatrix(int n) {
        int[][] matrixs = new int[n][n];
        int count = 1;
        int start = 0;int end = n;
        int row = 0, col = 0;

        while(end > 1){
            for(col = start; col < end - 1; col++){
                matrixs[start][col] = count++;
            }
            for(row = start; row < end - 1; row++){
                matrixs[row][end - 1] = count++;
            }
            for(col = end - 1; col > start; col--){
                matrixs[end - 1][col] = count++;
            }
            for(row = end - 1; row > start;row--){
                matrixs[row][start] = count++;
            }
            start++;
            end--;
        }
	if(n % 2 != 0){//奇数最中心的数
            matrixs[n / 2][n / 2] = n * n;
        }
        return matrixs;
    }
}

58. 区间和

思路:

采用for循环不断累加区间和会造成超时。
计算前缀和即下标0到下标i的和,区间[a,b]的区间和=前缀和[b]-前缀和[a-1]

import java.util.Scanner;

public class Main {
    public static void main(String[] args){
        Scanner sc = new Scanner(System.in);
        
        int n = sc.nextInt();
        int[] arr1 = new int[n];
        int[] sumRange = new int[n];
        
        int preSum = 0;
        for(int i = 0; i < n; i++){
            arr1[i] = sc.nextInt();
            preSum += arr1[i];
            sumRange[i] = preSum;
        }
        
        while(sc.hasNextInt()){
            int a = sc.nextInt();
            int b = sc.nextInt();
            
            int sum = 0;
            if(a == 0){
                sum = sumRange[b];
            }else{
                sum = sumRange[b] - sumRange[a - 1];
            }
            System.out.println(sum);
        }
        sc.close();
    }
}

反思:

不熟悉acm模式是做这道题最大的问题


44.开发商购买土地

思路:

前缀和暴力解法

import java.util.Scanner;

public class Main{
    public static void main(String[] args){
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        int m = sc.nextInt();
        int[][] area = new int[n][m];
        int sum = 0;
        //录入每块地的权值,并对权值求和
        for(int i = 0; i < n; i++){
            for(int j = 0; j < m; j++){
                area[i][j] = sc.nextInt();
                sum += area[i][j];
            }
        }
        //记录最小总价值差
        int minCut = Integer.MAX_VALUE;
        //每行求和
        int[] rowSum = new int[n];
        for(int i = 0; i < n; i++){
            for(int j = 0; j < m; j++){
                rowSum[i] += area[i][j];
            }
        }
        //每列求和
        int[] colSum = new int[m];
         for(int i = 0; i < m; i++){
            for(int j = 0; j < n; j++){
                colSum[i] += area[j][i];
            }
        }
        //求横向划分的最小差
        int rowCut = 0;
        for(int i = 0; i < n; i++){
            rowCut += rowSum[i];
            //减2*Math.abs(sum - 2 * rowCut),是求出剩余区域的权值和后求总价值之差
            minCut = minCut < Math.abs(sum - 2 * rowCut) ? minCut : Math.abs(sum - 2 * rowCut);
        }
        //求纵向划分的最小差
        int colCut = 0;
        for(int j = 0; j < m; j++){
            colCut += colSum[j];
            minCut = minCut < Math.abs(sum - 2 * colCut) ? minCut : Math.abs(sum - 2 * colCut);
        }
        
        System.out.println(minCut);
        sc.close();
    }
}

优化思路:

在横向和纵向遍历的时候,每遍历到行/列尾,与最小差比较,若小于就更新。

import java.util.Scanner;

public class Main{
    public static void main(String[] args){
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        int m = sc.nextInt();
        int sum = 0;
        int[][] area = new int[n][m];
        for(int i = 0;i < n;i++){
            for(int j = 0;j < m; j++){
                area[i][j]= sc.nextInt();
                sum += area[i][j];
            }
        }
        
        int minCut = Integer.MAX_VALUE;
        int rowSum = 0;
        for(int i = 0;i < n;i++){
            for(int j = 0;j < m; j++){
                rowSum += area[i][j];
                if(j == m - 1){
                    minCut = minCut < Math.abs(sum - 2 * rowSum) ? minCut : Math.abs(sum - 2 * rowSum);
                }
            }
        }
        int colSum = 0;
        for(int i = 0;i < m;i++){
            for(int j = 0;j < n; j++){
                colSum += area[j][i];
                if(j == n - 1){
                    minCut = minCut < Math.abs(sum - 2 * colSum) ? minCut : Math.abs(sum - 2 * colSum);
                }
            }
        }
        System.out.println(minCut);
        sc.close();
    }
}
posted @ 2024-09-04 00:29  九域奈落  阅读(8)  评论(0)    收藏  举报