You are given an m * n
matrix, mat
, and an integer k
, which has its rows sorted in non-decreasing order.
You are allowed to choose exactly 1 element from each row to form an array. Return the Kth smallest array sum among all possible arrays.
Example 1:
Input: mat = [[1,3,11],[2,4,6]], k = 5 Output: 7 Explanation: Choosing one element from each row, the first k smallest sum are: [1,2], [1,4], [3,2], [3,4], [1,6]. Where the 5th sum is 7.
Example 2:
Input: mat = [[1,3,11],[2,4,6]], k = 9 Output: 17
Example 3:
Input: mat = [[1,10,10],[1,4,5],[2,3,6]], k = 7 Output: 9 Explanation: Choosing one element from each row, the first k smallest sum are: [1,1,2], [1,1,3], [1,4,2], [1,4,3], [1,1,6], [1,5,2], [1,5,3]. Where the 7th sum is 9.
Example 4:
Input: mat = [[1,1,10],[2,2,9]], k = 7 Output: 12
Constraints:
m == mat.length
n == mat.length[i]
1 <= m, n <= 40
1 <= k <= min(200, n ^ m)
1 <= mat[i][j] <= 5000
mat[i]
is a non decreasing array.
Solution 1: Priority Queue
Generate the arrays in order.
Each node is {sum, idx_0, idx_1, …, idx_m},
Start with {sum_0, 0, 0, …, 0}.
For expansion, pick one row and increase its index
Time complexity: O(k * m ^ 2* log k)
Space complexity: O(k)
C++
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
// Author: Huahua class Solution { public: int kthSmallest(vector<vector<int>>& mat, int k) { const int m = mat.size(); const int n = mat[0].size(); priority_queue<vector<int>> q; vector<int> node(m + 1); // {-sum, idx_0, idx_1, ..., idx_m} for (int i = 0; i < m; ++i) node[0] -= mat[i][0]; q.push(node); set<vector<int>> seen{{node}}; while (!q.empty()) { const vector<int> cur = q.top(); q.pop(); if (--k == 0) return -cur[0]; for (int i = 1; i <= m; ++i) { if (cur[i] == n - 1) continue; vector<int> nxt(cur); ++nxt[i]; // increase i-th row's index. // Update sum. nxt[0] -= (mat[i - 1][nxt[i]] - mat[i - 1][nxt[i] - 1]); if (!seen.insert(nxt).second) continue; q.push(move(nxt)); } } return -1; } }; |