Leetcode题目
给你一个 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
这道题我本来想用回溯法列出所有可能,然后进行排序,果不其然超时了。
还有一种方法是这次重点要讲的,也就是使用堆结构+广度优先遍历的方法来求解。
具体思路:先把初始数组元素以及初始的数组和 加入小顶堆中,依次弹出堆中元素,弹出的元素代表了堆中存在的最小和的数组。当弹出到第k次时,即我们所要的答案。当每次弹出元素时,将该元素之和的所有可能数组放到堆中。
代码python版本
1 class Solution: 2 def kthSmallest(self, mat: List[List[int]], k: int) -> int: 3 m,n = len(mat),len(mat[0]) 4 pointer = [0]*m 5 cur_sum = 0 6 for i in range(m): 7 cur_sum += mat[i][0] 8 heap = [] 9 element = [cur_sum,tuple(pointer)] 10 heapq.heappush(heap,element) 11 repeat = set() 12 repeat.add(tuple(pointer)) 13 idx = 0 14 while idx<k: 15 res,pointer = heapq.heappop(heap) 16 for i,j in enumerate(pointer): 17 if j<n-1: 18 new_pointer = list(pointer) 19 new_pointer[i] = j+1 20 new_pointer = tuple(new_pointer) 21 if new_pointer not in repeat: 22 cur_sum = 0 23 for x,y in enumerate(list(new_pointer)): 24 cur_sum+=mat[x][y] 25 element = [cur_sum,new_pointer] 26 heapq.heappush(heap,element) 27 repeat.add(new_pointer) 28 idx+=1 29 return res