刷题日记 598. 范围求和 II

37 阅读1分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第19天,点击查看活动详情

一、题目描述:

598. 范围求和 II

给你一个 m x n 的矩阵 M ,初始化时所有的 0 和一个操作数组 op ,其中 ops[i] = [ai, bi] 意味着当所有的 0 <= x < ai 和 0 <= y < bi 时, M[x][y] 应该加 1。

在 执行完所有操作后 ,计算并返回 矩阵中最大整数的个数 。

示例 1:

image.png

输入: m = 3, n = 3,ops = [[2,2],[3,3]]
输出: 4
解释: M 中最大的整数是 2, 而且 M 中有4个值为2的元素。因此返回 4

示例 2:

输入: m = 3, n = 3, ops = [[2,2],[3,3],[3,3],[3,3],[2,2],[3,3],[3,3],[3,3],[2,2],[3,3],[3,3],[3,3]]
输出: 4

示例 3:

输入: m = 3, n = 3, ops = []
输出: 9

 

提示:

  • 1 <= m, n <= 4 * 10^4
  • 0 <= ops.length <= 10^4
  • ops[i].length == 2
  • 1 <= ai <= m
  • 1 <= bi <= n

二、思路分析:

  • 暴力法:生成一个数组,然后按照要求进行递增,最后找到有几个最大的数,返回
  • 理解题意
    • 要找的是最大数的个数
    • 每次要增加1的元素 行从 0 到 Math.min(m,ops[i][0]),列从 0 到 Math.min(n,ops[i][1])
    • 所以只需要找到 ops 数组中 第一列最小的数(表示到第几行),第二列最小的数(表示到第几列)
    • 因为增加1的元素都是从0行0列开始,找到 行列 最小值,也就是每一次操作,这些最小值内的元素都会增加
    • 最后返回 Math.min(m,xMin) * Math.mini(n,yMin) 即可,防止 溢出和不足

三、AC 代码:

class Solution {
    public int maxCountA(int m, int n, int[][] ops) {
        int[][] ans = new int[m][n];
        // 最重要的是模拟操作
        int max = Integer.MIN_VALUE;
        int count = 0;
        for(int p=0; p<ops.length; p++){
            int i=0, j=0;
            while(i<m && i<ops[p][0]){
                for(int k=0; k<ans[0].length;k++){
                    ans[i][k] += 1;
                    if(ans[i][k]>max){max=ans[i][k]; count=0;}
                    if(ans[i][k]==max){count++;}
                }
                i++;
            }
            while(j<n && j<ops[p][1]){
                for(int k=0; k<ans.length; k++){
                    ans[k][j] += 1;
                    if(ans[k][j]>max){max=ans[k][j]; count=0;}
                    if(ans[k][j]==max){count++;}
                }
                j++;
            }
        }
        return ops.length==0 ? m*n : count;
    }
    // 暴力法虽然能够解决问题,但是处理了很多无关的问题的计算
    // 因为每次增加的数都是 行从 0 到 min(m,aps[i][0]),列从 0 到 min(n,ops[i][1])
    // 所以只需要找到行的最小值,列的最小值,那么这些行列中的元素就是每次都被增加的,也就是最大的
    public int maxCount(int m, int n, int[][] ops) {
        int xMin=Integer.MAX_VALUE;
        int yMin=Integer.MAX_VALUE;
        for(int i=0; i<ops.length; i++){
            if(ops[i][0]<xMin) xMin = ops[i][0];
            if(ops[i][1]<yMin) yMin = ops[i][1];
        }
        return Math.min(xMin,m) * Math.min(yMin,n); 
    }
}