1. 程式人生 > 實用技巧 >378. Kth Smallest Element in a Sorted Matrix(大頂堆、小頂堆)

378. Kth Smallest Element in a Sorted Matrix(大頂堆、小頂堆)

Given anxnmatrix 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.

class Solution {
public:
    //一般在無序陣列中求第k大的數,利用堆排序。
    //priority_queue< int,vector<int>,greater<int> > 小頂堆
    //priority_queue< int,vector<int>,less<int> > 預設大頂堆
    int kthSmallest(vector<vector<int>>& matrix, int
k) { vector<int> m; for(int i=0;i<matrix.size();i++){ for(int j=0;j<matrix[i].size();j++){ m.push_back(matrix[i][j]); } } priority_queue< int,vector<int>,less<int> > p; for(int i=0;i<m.size();i++){
if(p.size()<k){ p.push(m[i]); }else{ if(p.top() > m[i]){ p.pop(); p.push(m[i]); } } } return p.top(); } };

//二分查詢

//這個二分不好想。

left = mid+1; 理解左邊個數小於k個,就得慢慢找到下一個left值,而且left值必定在矩陣中,左邊個數才會多一個。否則會一直加1.
class Solution {
public:
    //二分一般有兩種:1、按照下標進行二分,例如陣列有序 https://leetcode.com/problems/find-minimum-in-rotated-sorted-array/
    //或者陣列無序,要找滿足條件的元素個數,以陣列元素大小二分:https://leetcode.com/submissions/detail/134554396/
    int kthSmallest(vector<vector<int>>& matrix, int k) {
        //這題借鑑第二種二分思路,找k個數滿足條件
        int row = matrix.size();
        int col = matrix[0].size();
        int left=matrix[0][0],right=matrix[row-1][col-1];
        while(left<right){
            int mid = left+(right-left)/2;
            int count=0,j=col-1;
            //計算小於中間數的個數。
            for(int i = 0; i < row; i++) {
                while(j >= 0 && matrix[i][j] > mid) j--;
                count += (j + 1);
            }
            if(count < k){
                left = mid+1;
            }
            else {
                right = mid;
            }
        }
        return left;
    }
};