【LeetCode 每日一题】1439. 有序矩阵中的第 k 个最小数组和

69 阅读1分钟

1439. 有序矩阵中的第 k 个最小数组和

难度:困难

时间:2023/06/01


给你一个 m * n 的矩阵 mat,以及一个整数 k ,矩阵中的每一行都以非递减的顺序排列。

你可以从每一行中选出 1 个元素形成一个数组。返回所有可能数组中的第 k 个 最小 数组和。

示例 1:

输入:mat = [[1,3,11],[2,4,6]], k = 5
输出:7
解释:从每一行中选出一个元素,前 k 个和最小的数组分别是:
[1,2], [1,4], [3,2], [3,4], [1,6]。其中第 5 个的和是 7

示例 2:

输入:mat = [[1,3,11],[2,4,6]], k = 9
输出:17

示例 3:

输入:mat = [[1,10,10],[1,4,5],[2,3,6]], k = 7
输出:9
解释:从每一行中选出一个元素,前 k 个和最小的数组分别是:
[1,1,2], [1,1,3], [1,4,2], [1,4,3], [1,1,6], [1,5,2], [1,5,3]。其中第 7 个的和是 9

示例 4:

输入:mat = [[1,1,10],[2,2,9]], k = 7
输出:12

提示:

  • m == mat.length
  • n == mat.length[i]
  • 1 <= m, n <= 40
  • 1 <= k <= min(200, n ^ m)
  • 1 <= mat[i][j] <= 5000
  • mat[i] 是一个非递减数组

解题思路:

使用一个最小堆来存储和排序所有可能的数组和。开始时,将矩阵中每行的第一个元素相加,得到初始和和对应的索引列表。然后,将初始和和索引列表作为元组放入最小堆中。

在每次循环中,从最小堆中弹出当前和最小的元组。如果这是第k次弹出,那么当前和就是第k个最小数组和,直接返回。否则,对于每一行,将索引递增1,生成新的索引列表,并计算新的和。将新的和和索引列表组成元组,并将其放入最小堆中,同时将索引列表转换为元组,并加入到已访问的集合中。

重复这个过程,直到弹出第k个最小数组和,然后返回它作为结果

class Solution {
public:
    int kthSmallest(vector<vector<int>>& mat, int k) {
        vector<int> ans(mat[0]);
        for (int i = 1; i < mat.size(); ++i) {
            multiset<int> st;
            for (int x : ans) {
                for (int y : mat[i]) {
                    st.insert(x + y);
                }
            }
            ans.assign(st.begin(), st.end());
            ans.resize(min(k, (int)ans.size()));
        }
        return ans.back();
    }
};