算法day02-数组篇(2)

目录

  • 209.长度最小的子数组(滑动窗口)
    • 力扣100:无重复字符的最长子串
    • 力扣100:找到字符串中所有字母异位词
  • 59.螺旋矩阵
    • 华为真题螺旋矩阵:
    • 73题矩阵置零:
    • 48题旋转图像:
    • 240题搜索二维矩阵II:
  • 区间和(前缀和):
  • 开发商购买土地(二维前缀和):

 

一、长度最小的子数组

   力扣209题长度最小的子数组,这一题209. 长度最小的子数组 - 力扣(LeetCode)。主要是考察对滑动窗口的理解。

class Solution {
    public int minSubArrayLen(int target, int[] nums) {
        int left = 0;
        int sum = 0;
        int minLength = Integer.MAX_VALUE;
        for(int right = 0; right < nums.length; right++){
            sum += nums[right];
            while(sum >= target){       //不断缩小窗口但满足条件,直到得到一个最小的值
                minLength = Math.min(minLength, right - left + 1);
                sum -= nums[left];
                left++;
            }
        }
        return minLength == Integer.MAX_VALUE ? 0 : minLength;
    }
}
//时间复杂度:O(n),最多执行2n次操作
//空间复杂度:O(1),没有额外数组

【相关题目】

  • 3题无重复字符的最长子串:https://leetcode.cn/problems/longest-substring-without-repeating-characters/description/?envType=study-plan-v2&envId=top-100-liked

 

  • 438题找到字符串中所有字母异位词:https://leetcode.cn/problems/find-all-anagrams-in-a-string/description/?envType=study-plan-v2&envId=top-100-liked

 

二、螺旋矩阵II

 

   主要思路:就是定义四个指针,上下左右,重点在判断是否到达边界,然后按照图示的顺序来进行遍历。

class Solution {
    public int[][] generateMatrix(int n) {
        int left = 0,right = n-1;
        int top = 0, bottom = n-1;
        int[][] nums = new int[n][n];
        int a = 1;
        while(left <= right && top <= bottom){
            for(int i=left; i<=right; i++){
                nums[top][i] = a;
                a++;
            }
            top++;
            for(int i=top; i<=bottom; i++){
                nums[i][right] = a;
                a++;
            }
            right--;
            if(top <= bottom){
                for(int i=right; i>=left; i--){
                    nums[bottom][i] = a;
                    a++;
                }
                bottom--;
            }
            if(left <= right){
                for(int i=bottom; i>=top; i--){
                    nums[i][left] = a;
                    a++;
                }
                left++;
            }
        }
        return nums;
    }
}
//时间复杂度:O(n^2)
//空间复杂度:O(n^2)

 

【矩阵相关题目】

  • 华为真题螺旋矩阵:
  • 73题矩阵置零:
  • 48题旋转图像:
  • 240题搜索二维矩阵II:

三、区间和(前缀和)

  58. 区间和(第九期模拟笔试)

import java.util.Scanner;

public class Main{
    public static void main(String[] args){
        Scanner in = new Scanner(System.in);
        int n = in.nextInt();
        int[] nums = new int[n];
        for(int i=0; i<n; i++){
            nums[i] = in.nextInt();

        }

        int[] preSum = new int[n+1];
        for(int i=0; i<n; i++){    //注意这里不是n-1
            preSum[i+1] = preSum[i] + nums[i];
        }
        in.nextLine();
        while(in.hasNext()){
            String[] parts = in.nextLine().trim().split("\\s+");
            int num1 = Integer.parseInt(parts[0]);
            int num2 = Integer.parseInt(parts[1]);
            System.out.println(preSum[num2+1] - preSum[num1]);
        }
    }
}
//时间复杂度:O(N),构造前缀和O(N),每次查询O(1)
//空间复杂度:O(N),nums和preSum

 

四、开发商购买土地【有难度】

  44. 开发商购买土地(第五期模拟笔试)

  主要思路:构建二维矩阵的前缀和。然后分横向和纵向讨论两种切法得到的sum。

import java.util.*;
import java.lang.*;

public class Main{
    public static void main(String[] args){
        Scanner in = new Scanner(System.in);
        int n = in.nextInt();
        int m = in.nextInt();
        int[][] nums = new int[n][m];
        //读入矩阵
        for(int i=0; i<n; i++){
            for(int j=0; j<m; j++){
                nums[i][j] = in.nextInt();
                
            }
        }
        //计算行和列的前缀和
        int[][] preSum = new int[n+1][m+1];
        for(int i=0; i<n; i++){
            for(int j=0; j<m; j++){
                //这里可以画图理解,前两者-重叠部分+最右下角元素
                preSum[i+1][j+1] = preSum[i][j+1] + preSum[i+1][j]
                                    - preSum[i][j] + nums[i][j];
            }
        }

        int total = preSum[n][m];
        int minDiff = Integer.MAX_VALUE;
        //横向划分
        for(int rowCut = 1; rowCut < n ; rowCut++){
            int Asum = getSum(preSum, 0, 0, rowCut-1, m-1);
            int Bsum = total - Asum;
            minDiff = Math.min(minDiff, Math.abs(Asum-Bsum));
        }

        //纵向划分
        for(int colCut = 1; colCut < m; colCut++){
            int Asum = getSum(preSum, 0, 0, n-1, colCut-1);
            int Bsum = total - Asum;
            minDiff = Math.min(minDiff, Math.abs(Asum-Bsum));
        }
        System.out.println(minDiff);

    }

    // 获取区域 [r1, c1] ~ [r2, c2] 的总和
    public static int getSum(int[][] preSum, int r1, int c1, int r2, int c2){
        return preSum[r2+1][c2+1]
                - preSum[r1][c2+1]
                - preSum[r2+1][c1]
                + preSum[r1][c1];
    }
}
//时间复杂度:O(N+M)
//空间复杂度:O(N+M)

 

posted @ 2025-04-24 18:31  筱倩  阅读(354)  评论(0)    收藏  举报