leetcode
leetcode 2151 ~ 2200
删除每行中的最大值

删除每行中的最大值

难度:

标签:

题目描述

You are given an m x n matrix grid consisting of positive integers.

Perform the following operation until grid becomes empty:

  • Delete the element with the greatest value from each row. If multiple such elements exist, delete any of them.
  • Add the maximum of deleted elements to the answer.

Note that the number of columns decreases by one after each operation.

Return the answer after performing the operations described above.

 

Example 1:

Input: grid = [[1,2,4],[3,3,1]]
Output: 8
Explanation: The diagram above shows the removed values in each step.
- In the first operation, we remove 4 from the first row and 3 from the second row (notice that, there are two cells with value 3 and we can remove any of them). We add 4 to the answer.
- In the second operation, we remove 2 from the first row and 3 from the second row. We add 3 to the answer.
- In the third operation, we remove 1 from the first row and 1 from the second row. We add 1 to the answer.
The final answer = 4 + 3 + 1 = 8.

Example 2:

Input: grid = [[10]]
Output: 10
Explanation: The diagram above shows the removed values in each step.
- In the first operation, we remove 10 from the first row. We add 10 to the answer.
The final answer = 10.

 

Constraints:

  • m == grid.length
  • n == grid[i].length
  • 1 <= m, n <= 50
  • 1 <= grid[i][j] <= 100

代码结果

运行时间: 24 ms, 内存: 16.6 MB


/*
 * 思路:
 * 1. 使用stream对每一行进行处理,找到每一行的最大值并删除。
 * 2. 在每一步中,将所有最大值中的最大值加到答案中。
 */

import java.util.Arrays;
import java.util.Comparator;

public class SolutionStream {
    public int deleteGreatestValue(int[][] grid) {
        int totalSum = 0;
        while (Arrays.stream(grid).anyMatch(row -> row.length > 0)) {
            int maxInThisStep = Arrays.stream(grid)
                .filter(row -> row.length > 0)
                .mapToInt(row -> Arrays.stream(row).max().orElse(Integer.MIN_VALUE))
                .max()
                .orElse(Integer.MIN_VALUE);
            for (int[] row : grid) {
                if (row.length > 0) {
                    int maxVal = Arrays.stream(row).max().orElse(Integer.MIN_VALUE);
                    row = Arrays.stream(row).filter(num -> num != maxVal).toArray();
                }
            }
            totalSum += maxInThisStep;
        }
        return totalSum;
    }
}

解释

方法:

题解的主要思路是首先对矩阵的每一行进行逆序排序,使得每行的最大元素都位于行的开始。然后,通过迭代每一列,收集每行的最大未被删除的元素,并累加这些最大值。具体步骤如下:1. 遍历矩阵的每一行,对每一行进行逆序排序。2. 初始化一个等长于行数的数组 a,用于暂存每一列中的最大值。3. 对于每一列,通过列迭代收集每一行对应位置的元素,找出这些元素中的最大值,并累加到结果 sum 中。4. 返回累加的结果 sum。

时间复杂度:

O(m * n log n)

空间复杂度:

O(m)

代码细节讲解

🦆
在对每一行进行逆序排序后,为什么直接假设每行的最大元素始终位于行的开始,这种假设是否总是成立?
在对每一行进行逆序排序后,每行的元素按照从大到小的顺序排列,因此每行的第一个元素自然是该行的最大值。这种假设在我们已经将每行进行逆序排序后总是成立,因为排序保证了最大值始终出现在行的开始位置。
🦆
如何处理当矩阵的列数多于某些行的元素个数时的情况,即如果某一行中的元素被完全删除,后续列的迭代如何处理?
在题解中,每次操作删除每行的最大值时,如果某一行的元素提前被完全删除,则在后续的列迭代中,此行将不再提供任何元素。在实际实现时,应当检查每行的元素是否还存在,如果某行已无元素,其对应在数组a中的值应当被忽略或设为一个不影响最大值选择的较小值,例如0(假设所有元素均为正数)。这样可以确保不会对总和计算造成影响。
🦆
在初始化数组a用于存储每一列的最大值时,为什么选择长度等于行数,而不是列数?
在初始化数组a时,数组的长度设置为行数,是因为在每次迭代过程中,我们关注的是从每一列中收集每一行的对应元素,并找出这些元素中的最大值。由于每次操作都是逐行观察,每行只会对应一个元素进入到数组a中,因此数组a的长度应该与行数相等。如果设置为列数,将无法正确反映每次操作中每行提供的元素,因为行数定义了每次操作的元素个数上限。

相关问题