378. Kth Smallest Element in a Sorted Matrix
Given a n x n matrix where each of the rows and columns are sorted in ascending order, find the kth smallest element in the matrix.
Note that it is the kth smallest element in the sorted order, not the kth distinct element.
Example:
matrix = [
[ 1, 5, 9],
[10, 11, 13],
[12, 13, 15]
],
k = 8,
return 13.
Note:
You may assume k is always valid, 1 ≤ k ≤ n2.
题意:
给出一个矩阵,其中每一行每一列都是递增的,求出这个矩阵中第K小的数。
解答①:
暴力求解,对矩阵中的所有元素进行排序,输出排序后得到的数组的第k-1项即可。
代码:[cpp] view plain
复杂度:
因为矩阵中有n^2个元素,所以遍历矩阵中的元素的时间复杂度是O(n^2),对得到的数组进行排序的时间复杂度是O(n^2 * logn^2)=O(n^2 * logn)。所以暴力求解这个问题的时间复杂度是O(n^2 * logn)。
解法②:
上述解法的时间复杂度之所以很大,是因为在上面的情况中并没有充分第利用到题目给的每一行每一列递增的条件。为了解决这个问题,我自己在纸上面演算了一下如何手工求解这个问题。
所以对于求解上述矩阵中第k小的元素是什么,我会从左上角的这个最小的元素开始进行计数,再根据图中的步骤来寻找下一个最小的元素。下面的代码就是模拟上图的步骤来解决这个问题。
代码:[cpp] view plain
复杂度:
通过这一种算法,每一次寻找下一个小的元素的时候,最坏情况下是需要遍历k列的,所以时间复杂度是O(kn)。又因为k是可以达到n^2的, 所以最坏情况下这个算法的时间复杂度是O(n^3)。
其实这个算法有一个问题,就是每一次寻找下一个小的元素的时候,是没有必要进行遍历每一个元素的,因为原先的矩阵具有每一行每一列递增的性质。我尝试着对上面的算法进行改进,但是始终有BUG的存在,边界情况考虑实现地不是很好。所以没有列出新的解。
由于上面两种解法都具有较高的时间复杂度,所以我有去搜索看看该题有没有比较简洁的做法。
解法③:
使用一个最大堆,然后遍历这个矩阵,将其加入堆。根据最大堆的性质,大的元素会排到最前面。然后判断当前堆中的元素有没有大于K个,要是大于K个的话,就将首元素删掉。循环结束后,堆中的首元素就是第K小的元素。[cpp] view plain
复杂度:
将矩阵中的元素遍历了一遍,因为矩阵中有n^2个元素,所以时间复杂度O(n^2)。从堆里面删除一个元素的复杂度为O(logn)。所以总的时间复杂度为O(n^2)。