378. Kth Smallest Element in a Sorted Matrix

来源:互联网 发布:赛尔网络 招聘 编辑:程序博客网 时间:2024/06/05 17:54

1.Question

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.

2.Code

codeA

class Solution {public:    int kthSmallest(vector<vector<int>>& matrix, int k) {        priority_queue<int, vector<int>> q;        for (int i = 0; i < matrix.size(); ++i) {            for (int j = 0; j < matrix[i].size(); ++j) {                q.emplace(matrix[i][j]);                if (q.size() > k) q.pop();            }        }        return q.top();    }};

codeB

class Solution {public:    int kthSmallest(vector<vector<int>>& matrix, int k) {        int size = matrix.size();        int left = matrix[0][0];        int right = matrix.back().back();        while(left < right)        {            int mid = left + 0.5*(right - left);            int count = 0;            for(int i = 0; i < size; i++)            {                count += upper_bound(matrix[i].begin(), matrix[i].end(), mid) - matrix[i].begin();            }            if(count < k) left = mid + 1;            else right = mid;        }        return left;    }};


codeC

class Solution {public:    int kthSmallest(vector<vector<int>>& matrix, int k) {        int left = matrix[0][0];        int right = matrix.back().back();        while(left < right)        {            int mid = left + 0.5 *(right - left);            int count = search_count(matrix, k, mid);            if(count < k) left = mid + 1;            else right = mid;        }        return left;    }    int search_count(vector<vector<int>>& matrix, int k, int target) {        int ROW = matrix.size();        int row = 0;        int col = ROW - 1;        int count = 0;        while(row < ROW & col >= 0)        {            int temp = matrix[row][col];            if(target < temp) col--;            else { count += col + 1; row++;}        }        return count;    }};


3.Note

a. CodeA利用了最大堆priority_queue(这是个有序的堆,先大致了解一下,以后再用),对矩阵进行一次遍历,并只保留前k小的数字。这里要注意的是,对于新来的数字插入到最大堆里面的时候,源码应该用的也是二分查找的方法,能够快速插入到最大堆里。如果堆的长度大于k了,则弹出最大的数字,这样能保证二分查找时候的速度。

b. CodeB则直接利用到二分查找去找对应的数字,并且利用STL的upper_bound 统计每一行,小于等于mid的个数,其源码也是利用二分查找。然后收敛到一个数字上,就是left了。假设matrix是n x n的,进行n次upper_bound就是nlgn了,然后二分找数字的是lgX, X=最大数字-最小数字. 所以复杂度是O(nlgn*lgX).

c. CodeC在统计count的时候,不需要每一行都进行二分查找去统计每一行小于mid的数,可以利用这个矩阵的特点,巧妙运用,找出以mid为分界面的分界面。这种方法的的复杂度就是O(n*lgX)了。

1 0