携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第19天,点击查看活动详情
一、题目描述:
给你一个 m x n 的矩阵 M ,初始化时所有的 0 和一个操作数组 op ,其中 ops[i] = [ai, bi] 意味着当所有的 0 <= x < ai 和 0 <= y < bi 时, M[x][y] 应该加 1。
在 执行完所有操作后 ,计算并返回 矩阵中最大整数的个数 。
示例 1:
输入: 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);
}
}