You are given an m x n
matrix mat
that has its rows sorted in non-decreasing order and an integer k
. You are allowed to choose exactly one element from each row to form an array. Return the k<sup>th</sup>
* smallest array sum among all possible arrays*. For example:
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.
mat = [[1,3,11],[2,4,6]], k = 9
Output: 17
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.
Explain and write code to solve this problem efficiently.
This problem asks us to find the k-th smallest sum among all possible arrays formed by picking one element from each row of a given matrix. The rows of the matrix are sorted in non-decreasing order.
A straightforward approach would be to generate all possible arrays, calculate their sums, sort the sums, and then return the k-th smallest sum. However, this approach has exponential time complexity because the number of possible arrays is n^m
, where n
is the number of columns and m
is the number of rows.
import itertools
def kth_smallest_matrix_sum_brute_force(mat, k):
"""Brute force solution to find the k-th smallest matrix sum."""
rows = len(mat)
cols = len(mat[0])
# Generate all possible combinations of elements (one from each row)
combinations = list(itertools.product(*mat))
# Calculate the sum of each combination
sums = [sum(combination) for combination in combinations]
# Sort the sums and return the k-th smallest
sums.sort()
return sums[k - 1]
# Example usage:
mat = [[1, 3, 11], [2, 4, 6]]
k = 5
result = kth_smallest_matrix_sum_brute_force(mat, k)
print(f"The {k}-th smallest sum (brute force): {result}") # Output: 7
A more efficient approach is to use a min-heap to keep track of the k
smallest sums found so far. We start by initializing the heap with the sum of the first elements from each row. Then, we repeatedly extract the smallest sum from the heap and generate new candidate sums by replacing one of the elements in the current array with the next element in its corresponding row. We add these new sums to the heap if they are not already present and if the heap size is less than k or if the new sum is smaller than the largest sum in the heap.
import heapq
def kth_smallest_matrix_sum(mat, k):
"""Finds the k-th smallest matrix sum using a min-heap."""
m, n = len(mat), len(mat[0])
# Initialize the heap with the sum of the first elements from each row
heap = [(sum(mat[i][0] for i in range(m)), tuple([0] * m))]
visited = set()
visited.add(tuple([0] * m))
for _ in range(k):
curr_sum, indices = heapq.heappop(heap)
# If this is the k-th smallest sum, return it
if _ == k - 1:
return curr_sum
# Generate new candidate sums by replacing one element with the next in its row
for i in range(m):
if indices[i] + 1 < n:
new_indices = list(indices)
new_indices[i] += 1
new_indices = tuple(new_indices)
if new_indices not in visited:
new_sum = curr_sum - mat[i][indices[i]] + mat[i][new_indices[i]]
heapq.heappush(heap, (new_sum, new_indices))
visited.add(new_indices)
return -1 # Should not reach here if k is valid
# Example usage:
mat = [[1, 3, 11], [2, 4, 6]]
k = 5
result = kth_smallest_matrix_sum(mat, k)
print(f"The {k}-th smallest sum (heap): {result}") # Output: 7
mat = [[1, 3, 11], [2, 4, 6]]
k = 9
result = kth_smallest_matrix_sum(mat, k)
print(f"The {k}-th smallest sum (heap): {result}") # Output: 17
mat = [[1, 10, 10], [1, 4, 5], [2, 3, 6]]
k = 7
result = kth_smallest_matrix_sum(mat, k)
print(f"The {k}-th smallest sum (heap): {result}") # Output: 9
k
times, and in each iteration, we perform heap operations (push and pop) which take O(log k) time. In the inner loop, we iterate through each row m
. The number of visited states can be at most k
. Thus, the overall time complexity is O(k * m * log k).k
elements, and the visited set can also contain at most k
elements. Therefore, the space complexity is O(k).m = 0
), there are no possible sums. We should return 0 or raise an exception depending on the desired behavior.k
is less than 1 or greater than the total number of possible arrays (nm), we should raise an exception or return an appropriate error value.It is also possible to solve this problem using binary search. You can binary search for the kth smallest sum. For each mid
value, determine if there are at least k
sums that are <= mid
. This requires a different approach, and the complexity may vary.