方法一
解题思路
m行n列的矩阵每一行相当于一个排好序的数组,要求出第k大的数,需要对这m行一维数组进行最小堆的建立,选出第k大的元素。
可以用STL中的优先队列实现,这里实现需要定义一个结构体,同时对结构体的小于号也要进行重载。
结构体定义
struct Point
{
int val
;
int x
;
int y
;
Point(){}
Point(int _val
, int _x
, int _y
): val(_val
), x(_x
), y(_y
){}
bool operator< (const Point p
) const{
return val
> p
.val
;
}
};
代码
class Solution {
public:
int kthSmallest(vector
<vector
<int>>& matrix
, int k
) {
if(matrix
.size() == 0 || matrix
[0].size() == 0){
return 0;
}
int m
= matrix
.size();
int n
= matrix
[0].size();
struct Point
{
int val
;
int x
;
int y
;
Point(){}
Point(int _val
, int _x
, int _y
): val(_val
), x(_x
), y(_y
){}
bool operator< (const Point p
) const{
return val
> p
.val
;
}
};
priority_queue
<Point
> myQueue
;
for(int i
= 0; i
< m
; ++i
){
myQueue
.push(Point(matrix
[i
][0], i
, 0));
}
Point ans
;
int i
= 0;
while(!myQueue
.empty() && i
< k
){
ans
= myQueue
.top();
myQueue
.pop();
i
++;
if(ans
.y
!= n
- 1){
myQueue
.push(Point(matrix
[ans
.x
][ans
.y
+ 1], ans
.x
, ans
.y
+ 1));
}
}
return ans
.val
;
}
};
复杂度分析
假设矩阵 n行,m列.
时间复杂度:插入的时间复杂度为 O(log n),故总共 O(k logn),最差 O(n*n logn)
空间复杂度:空间恒定为 O(n).
方法二
解题思路
数组中最小的值为 matrix[0][0] ,最大为 matrix[m - 1][n - 1] ,第k个数一定在他们值中间,定义变量 left 和 right 分别等于 matrix[0][0] 和 matrix[m - 1][n - 1]]。
选择 matrix[0][0] 和 matrix[m - 1][n - 1] 中间的数,用二分查找,以该数 mid 为分界线,将矩阵分为左右两个部分,求出比 mid 小的数在矩阵中的个数。
若小于mid值的个数大于等于k,证明mid太大了,right = mid。
否则,left = mid + 1。直到left = right。
代码
class Solution {
public:
int count(vector
<vector
<int>>& matrix
, int mid
){
int m
= matrix
.size();
int n
= matrix
[0].size();
int ans
= 0;
int j
= 0;
for(int i
= m
- 1; i
>= 0; --i
){
while(j
< n
&& matrix
[i
][j
] <= mid
){
++j
;
}
ans
+= j
;
}
return ans
;
}
int kthSmallest(vector
<vector
<int>>& matrix
, int k
) {
if(matrix
.size() == 0 || matrix
[0].size() == 0){
return 0;
}
int m
= matrix
.size();
int n
= matrix
[0].size();
int left
= matrix
[0][0], right
= matrix
[m
- 1][n
- 1];
while(left
< right
){
int mid
= left
+ (right
- left
) / 2;
if(count(matrix
, mid
) >= k
){
right
= mid
;
}
else{
left
= mid
+ 1;
}
}
return left
;
}
};
复杂度分析
时间复杂度:O(n log n),查找次数 O(logn),每次操作次数 O(n).
空间复杂度: O(1).