[C++] LeetCode 378. 有序矩阵中第K小的元素

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/lv1224/article/details/81055471

题目

给定一个 n x n 矩阵,其中每行和每列元素均按升序排序,找到矩阵中第k小的元素。
请注意,它是排序后的第k小元素,而不是第k个元素。

示例:
matrix = [
[ 1, 5, 9],
[10, 11, 13],
[12, 13, 15]
],
k = 8,
返回 13。

说明:
你可以假设k 的值永远是有效的, 1 ≤ k ≤ n2

思路解析

这题有两种解法,最简单的遍历整个矩阵,其次考虑题目提到的关键信息,升序排序可以考虑二分法

方法一 遍历矩阵

用一个优先级队列保存数组,然后遍历矩阵,维护优先级队列大小为k,这样遍历完,直接取出优先级队列top即可
代码

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

        }
        return q.top();
    }
};

二分法

二分法一般常用的有两种做法,一个是常规的有序数组,然后索引二分查找目标元素,如lower_boundupper_bound等,另外一种是无序数组,但是知道了上下限之后,通过二分上下限查找目标元素,这一题采用的就是这种方法。

class Solution {
public:
    int kthSmallest(vector<vector<int>>& matrix, int k) {
        int n=matrix.size(),l=matrix[0][0],r=matrix[n-1][n-1]+1;
        int mid=l;
        while(l<r){
            mid=l+(r-l)/2;
            int cnt=0,cnt2=0;
            for(int i=0;i<n;i++){
                auto &v=matrix[i];
                cnt+=lower_bound(v.begin(),v.end(),mid)-v.begin();
                cnt2+=upper_bound(v.begin(),v.end(),mid)-v.begin();
            }
            if(cnt<k&&cnt2>=k) return mid;
            if(cnt<k) l=mid+1;
            else r=mid;
        }
        return mid;
    }
};

猜你喜欢

转载自blog.csdn.net/lv1224/article/details/81055471