Easy
题目描述
给你一个由正整数组成的 m x n 矩阵 grid。
执行下述操作,直到 grid 变为空矩阵:
- 从每一行删除值最大的元素。如果存在多个这样的值,删除其中任何一个。
- 将删除元素中的最大值添加到答案中。
注意 每执行一次上述操作,列的数量都会减 1。
返回执行上述操作后的答案。
示例 1:
输入:grid = [[1,2,4],[3,3,1]]
输出:8
解释:上图展示了每一步中删除的值。
- 第一步操作中,我们从第一行删除 4 ,从第二行删除 3(注意,有两个单元格的值为 3 ,我们可以删除任意一个)。在答案上加 4 。
- 第二步操作中,我们从第一行删除 2 ,从第二行删除 3 。在答案上加 3 。
- 第三步操作中,我们从第一行删除 1 ,从第二行删除 1 。在答案上加 1 。
最终答案 = 4 + 3 + 1 = 8 。
示例 2:
输入:grid = [[10]]
输出:10
解释:上图展示了每一步中删除的值。
- 第一步操作中,我们从第一行删除 10 。在答案上加 10 。
最终答案 = 10 。
提示:
m == grid.lengthn == grid[i].length1 <= m, n <= 501 <= grid[i][j] <= 100
解题思路
这道题的核心思路是模拟删除过程。我们需要在每轮操作中找到每行的最大值,然后取这些最大值中的最大值加入答案。
解法一:排序法(推荐) 最直观的方法是对每行进行排序,这样每行的最大值就在末尾。每次操作时,我们取每行的最后一个元素(最大值),找出其中的最大值累加到答案中,然后从每行移除最后一个元素。
解法二:堆/优先队列法 可以为每行维护一个最大堆,每次取堆顶元素参与比较。
解法三:暴力模拟法 每次遍历矩阵找每行最大值,然后标记为已删除。
从效率角度看,排序法是最简洁高效的。由于每行只需排序一次,后续操作都是 O(1) 的取值,整体复杂度较优。而且代码实现简单,不容易出错。
具体实现时,我们先对每行进行降序排序,然后进行 n 轮操作(n 为列数)。每轮从每行取第一个元素找最大值,然后删除这些元素。
代码实现
class Solution {
public:
int deleteGreatestValue(vector<vector<int>>& grid) {
int m = grid.size(), n = grid[0].size();
// 对每一行进行降序排序
for (int i = 0; i < m; i++) {
sort(grid[i].begin(), grid[i].end(), greater<int>());
}
int answer = 0;
// 执行n轮操作
for (int col = 0; col < n; col++) {
int maxVal = 0;
// 找出当前轮次每行最大值中的最大值
for (int row = 0; row < m; row++) {
maxVal = max(maxVal, grid[row][col]);
}
answer += maxVal;
}
return answer;
}
};
class Solution:
def deleteGreatestValue(self, grid: List[List[int]]) -> int:
m, n = len(grid), len(grid[0])
# 对每一行进行降序排序
for i in range(m):
grid[i].sort(reverse=True)
answer = 0
# 执行n轮操作
for col in range(n):
max_val = 0
# 找出当前轮次每行最大值中的最大值
for row in range(m):
max_val = max(max_val, grid[row][col])
answer += max_val
return answer
public class Solution {
public int DeleteGreatestValue(int[][] grid) {
int m = grid.Length, n = grid[0].Length;
// 对每一行进行降序排序
for (int i = 0; i < m; i++) {
Array.Sort(grid[i], (a, b) => b.CompareTo(a));
}
int answer = 0;
// 执行n轮操作
for (int col = 0; col < n; col++) {
int maxVal = 0;
// 找出当前轮次每行最大值中的最大值
for (int row = 0; row < m; row++) {
maxVal = Math.Max(maxVal, grid[row][col]);
}
answer += maxVal;
}
return answer;
}
}
var deleteGreatestValue = function(grid) {
const m = grid.length, n = grid[0].length;
// 对每一行进行降序排序
for (let i = 0; i < m; i++) {
grid[i].sort((a, b) => b - a);
}
let answer = 0;
// 执行n轮操作
for (let col = 0; col < n; col++) {
let maxVal = 0;
// 找出当前轮次每行最大值中的最大值
for (let row = 0; row < m; row++) {
maxVal = Math.max(maxVal, grid[row][col]);
}
answer += maxVal;
}
return answer;
};
复杂度分析
| 复杂度类型 | 值 | 说明 |
|---|---|---|
| 时间复杂度 | O(m×n×log n) | 对m行分别排序需要O(m×n×log n),后续n轮操作每轮O(m),总计O(m×n×log n) |
| 空间复杂度 | O(1) | 只使用常量额外空间,原地排序 |
相关题目
- . Equal Row and Column Pairs (Medium)