矩阵中的和

标签: 数组 矩阵 排序 模拟 堆(优先队列)

难度: Medium

给你一个下标从 0 开始的二维整数数组 nums 。一开始你的分数为 0 。你需要执行以下操作直到矩阵变为空:

  1. 矩阵中每一行选取最大的一个数,并删除它。如果一行中有多个最大的数,选择任意一个并删除。
  2. 在步骤 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 。

提示:

  • 1 <= nums.length <= 300
  • 1 <= nums[i].length <= 500
  • 0 <= nums[i][j] <= 103

Submission

运行时间: 74 ms

内存: 32.9 MB

class Solution:
    def matrixSum(self, nums: List[List[int]]) -> int:
        Score = 0
        for i in range(len(nums)):
            nums[i].sort()
        for j in range(len(nums[0])):
            tmp = []
            for i in range(len(nums)):
                tmp.append(nums[i][j])
            Score += max(tmp)
        return Score

Explain

题解的整体思路是首先将每一行的元素进行排序,确保每一行的最大元素位于行的末端。然后,按列遍历排序后的矩阵,每次遍历中,从每一行的当前列元素中找到最大值,累加到分数中。这种方法利用了排序后的行结构,每次从列中选取元素时,可以直接访问对应位置的元素,简化了每次查找行最大值的操作。

时间复杂度: O(n * m log m)

空间复杂度: O(n)

class Solution:
    def matrixSum(self, nums: List[List[int]]) -> int:
        Score = 0
        # 将每一行排序,确保每行最大的数在最后
        for i in range(len(nums)):
            nums[i].sort()
        # 遍历每一列
        for j in range(len(nums[0])):
            tmp = []
            # 从每一行的当前列收集元素
            for i in range(len(nums)):
                tmp.append(nums[i][j])
            # 找到当前列的最大值,加到分数中
            Score += max(tmp)
        return Score

Explore

在这个算法中,选择先对每一行进行排序是为了简化每次从行中选取最大元素的操作。通过排序,每行的最大元素都被放在行的末端,这样在后续的列遍历操作中可以直接通过索引访问每行的最大元素。这种方法减少了在每次操作中寻找最大值的计算复杂度,从而提高了整体算法的效率。排序的主要影响是使得每一行的元素按照升序排列,保证了在列遍历中可以直接访问到当前列(步骤)中的最大值。

这种方法可以保证不会遗漏每行的最大值,因为每一行已经被预先排序,所以每次迭代在收集元素时,都是按照从最小到最大的顺序进行。每次迭代结束时,总是能够收集到当前列中的最大元素,并将其加入到分数中。因此,虽然每次操作都是从当前未被删除的最小元素开始,但最终总能覆盖到每一行的最大元素。

在这个算法中,如果有多行在同一列具有相同的最大值,这种情况将被正常处理,因为算法是在每一列的迭代过程中,从所有剩余的行元素中选取最大值加到分数中。即使多行的元素相同,选择其中的最大值加到分数中,也不会影响分数的正确累加,因为每次都是添加当前列的最大值。所以,即便多行列值相同,也只会将它们中的一个最大值计入分数,符合题目的要求。