Medium
题目描述
给你一个下标从 0 开始的二维整数数组 nums。一开始你的分数为 0。你需要执行以下操作直到矩阵变为空:
- 从矩阵的每一行中,选择最大的那个数并移除它。在平局的情况下,你可以选择其中任何一个。
- 在第 1 步选出的所有数字中,选择最大的那个数,将它加到你的分数中。
返回最终的分数。
示例 1:
输入:nums = [[7,2,1],[6,4,2],[6,5,3],[3,2,1]]
输出:15
解释:第一次操作中,我们移除 7、6、6 和 3,然后将 7 加到分数中。
接下来移除 2、4、5 和 2,将 5 加到分数中。
最后移除 1、2、3 和 1,将 3 加到分数中。
因此,最终分数是 7 + 5 + 3 = 15。
示例 2:
输入:nums = [[1]]
输出:1
解释:我们移除 1 并将它加到答案中,返回 1。
约束条件:
1 <= nums.length <= 3001 <= nums[i].length <= 5000 <= nums[i][j] <= 10³
解题思路
解题思路
这道题目的核心在于理解操作过程:每轮操作都是从每行选择最大值,然后在这些最大值中选择最大的加入分数。
方法一:排序模拟(推荐) 观察题目提示,我们可以将每行按降序排列。这样做的好处是:
- 第一轮操作:每行第0列的元素就是各行最大值
- 第二轮操作:每行第1列的元素就是各行剩余元素的最大值
- 以此类推…
因此,问题转化为:对每行排序后,求每列的最大值之和。
方法二:优先队列模拟 也可以为每行维护一个最大堆,每次取出各行的最大值,然后找出其中最大的加入分数。但这种方法时间复杂度较高。
排序方法更直观高效,时间复杂度为 O(m×n×log n),其中 m 是行数,n 是列数。空间复杂度为 O(1)(原地排序)。
代码实现
class Solution {
public:
int matrixSum(vector<vector<int>>& nums) {
// 对每行进行降序排序
for (auto& row : nums) {
sort(row.begin(), row.end(), greater<int>());
}
int score = 0;
int cols = nums[0].size();
// 遍历每一列,找出每列的最大值
for (int j = 0; j < cols; j++) {
int maxInCol = 0;
for (int i = 0; i < nums.size(); i++) {
maxInCol = max(maxInCol, nums[i][j]);
}
score += maxInCol;
}
return score;
}
};
class Solution:
def matrixSum(self, nums: List[List[int]]) -> int:
# 对每行进行降序排序
for row in nums:
row.sort(reverse=True)
score = 0
cols = len(nums[0])
# 遍历每一列,找出每列的最大值
for j in range(cols):
max_in_col = 0
for i in range(len(nums)):
max_in_col = max(max_in_col, nums[i][j])
score += max_in_col
return score
public class Solution {
public int MatrixSum(int[][] nums) {
// 对每行进行降序排序
foreach (var row in nums) {
Array.Sort(row, (a, b) => b.CompareTo(a));
}
int score = 0;
int cols = nums[0].Length;
// 遍历每一列,找出每列的最大值
for (int j = 0; j < cols; j++) {
int maxInCol = 0;
for (int i = 0; i < nums.Length; i++) {
maxInCol = Math.Max(maxInCol, nums[i][j]);
}
score += maxInCol;
}
return score;
}
}
var matrixSum = function(nums) {
// 对每行进行降序排序
for (let row of nums) {
row.sort((a, b) => b - a);
}
let score = 0;
const cols = nums[0].length;
// 遍历每一列,找出每列的最大值
for (let j = 0; j < cols; j++) {
let maxInCol = 0;
for (let i = 0; i < nums.length; i++) {
maxInCol = Math.max(maxInCol, nums[i][j]);
}
score += maxInCol;
}
return score;
};
复杂度分析
| 复杂度类型 | 分析 |
|---|---|
| 时间复杂度 | O(m×n×log n),其中 m 是行数,n 是列数。排序每行需要 O(n log n),共 m 行 |
| 空间复杂度 | O(1),原地排序,只使用常数额外空间 |