题目
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.
最简单的方法就是遍历矩阵,在map中记录下每个元素出现的次数,由于map会自动根据key值排序,只需在遍历map时用k减去当前元素出现的次数,小于0时即为所求,这种方法时间复杂度过于高,discuss中有对矩阵使用binary search的方法,由于矩阵每一行已经排好序,所以matrix[0][0]和matrix[size-1][size-1]分别为最小值和最大值,算出中值m,对每行的vector使用upper_bound查找,得出每行小于m的元素个数,如果该值小于k,则m取值过小,最小值改为m+1重新执行上面的步骤,反之m过大,最大值改为m重新执行,这样就会逐渐减小检索区间,最终当l>=r时,就找到了所求的元素,详细内容参考Clean solution with detailed explanation in C++
map:
class Solution {
public:
int kthSmallest(vector<vector<int>>& matrix, int k) {
map<int,int> m;
for(int i=0;i<matrix.size();++i)
{
for(int j=0;j<matrix[i].size();++j)
{
m[matrix[i][j]]++;
}
}
map<int,int>::iterator map_it=m.begin();
while(k>0)
{
k-=map_it->second;
map_it++;
}
return (--map_it)->first;
}
};
binary search:
class Solution {
public:
int kthSmallest(vector<vector<int>>& matrix, int k)
{
int size = matrix.size(), l = matrix[0][0], r = matrix[size-1][size-1];
while(l < r)
{
int smaller = 0, m = l+((r-l)>>1);//smaller记录小于等于m值的个数
for(int i = 0; i < size; ++i) //对矩阵的每一行
smaller += upper_bound(matrix[i].begin(), matrix[i].end(), m)-matrix[i].begin();//计算每行小于等于m值的元素个数
smaller<k? l=m+1 : r=m;//根据smaller与k值大小调整上下边界
}
return r;
}
};