378有序矩阵中第 K 小的元素(归并+小顶堆)

1、题目描述

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

提示:

  • n == matrix.length
  • n == matrix[i].length
  • 1 <= n <= 300
  • -10^9 <= matrix[i][j] <= 10^9
  • 题目数据 保证 matrix 中的所有行和列都按 非递减顺序 排列
  • 1 <= k <= n^2

2、示例

输入:matrix = [[1,5,9],[10,11,13],[12,13,15]], k = 8
输出:13
解释:矩阵中的元素为 [1,5,9,10,11,12,13,13,15],第 8 小元素是 13

3、题解

基本思想:归并+小顶堆,和373查找和最小的K对数字思想一致,维护N维大小的指针表示N行数组的位置,每次都要从N个指针里取最小的pop,然后将加入的值的下一个值入堆。

#include<iostream>
#include<vector>
#include<algorithm>
#include<queue>
using namespace std;
class Solution {
public:
    int kthSmallest(vector<vector<int>>& matrix, int k) {
        //简化版:pair<int,int>分别是matrix中的横纵坐标,但是因为是自己实现的堆所以性能上不如直接使用priority_queue
        vector<pair<int,int>> min_heap;
        int res;
        for(int i=0;i<matrix.size();i++)
        {
            min_heap.push_back({i,0});
            push_heap(min_heap.begin(),min_heap.end(),[matrix](pair<int,int> &a,pair<int,int> &b){return matrix[a.first][a.second]>matrix[b.first][b.second];});
        }
        while(k--)
        {
            pair<int,int> tmp=min_heap[0];
            res=matrix[tmp.first][tmp.second];
            pop_heap(min_heap.begin(),min_heap.end(),[matrix](pair<int,int> &a,pair<int,int> &b){return matrix[a.first][a.second]>matrix[b.first][b.second];});
            min_heap.pop_back();
            tmp.second++;
            if(tmp.second<matrix.size())
            {
                min_heap.push_back(tmp);
                push_heap(min_heap.begin(),min_heap.end(),[matrix](pair<int,int> &a,pair<int,int> &b){return matrix[a.first][a.second]>matrix[b.first][b.second];});
            }
        }
        return res;
    }
};
class Solution {
public:
    int kthSmallest(vector<vector<int>>& matrix, int k) {
        //基本思想:归并+小顶堆,和373查找和最小的K对数字思想一致
        //维护N维大小的指针表示N行数组的位置,每次都要从N个指针里取最小的pop,然后将加入的值的下一个值入堆
        int res;
        vector<int> index(matrix.size(),0);
        vector<int> min_heap;
        for(int i=0;i<matrix.size();i++)
        {
            min_heap.push_back(i);
            push_heap(min_heap.begin(),min_heap.end(),[matrix,index](int& a,int& b){return matrix[a][index[a]]>matrix[b][index[b]];});
        }
        while(k--)
        {
            res=matrix[min_heap[0]][index[min_heap[0]]];
            index[min_heap[0]]++;
            int temp=min_heap[0];
            pop_heap(min_heap.begin(),min_heap.end(),[matrix,index](int& a,int& b){return matrix[a][index[a]]>matrix[b][index[b]];});
            min_heap.pop_back();
            if(index[temp]<matrix.size())
            {
                min_heap.push_back(temp);
                push_heap(min_heap.begin(),min_heap.end(),[matrix,index](int& a,int& b){return matrix[a][index[a]]>matrix[b][index[b]];});
            }
        }
        return res;
    }
};
class Solution1 {
public:
    int kthSmallest(vector<vector<int>>& matrix, int k) {
        struct point {
            int val, x, y;
            point(int val, int x, int y) : val(val), x(x), y(y) {}
            point(){}
            bool operator> (const point& a) const { return this->val > a.val; }
        };
        point res;
        priority_queue<point,vector<point>,greater<point>> min_heap;
        for(int i=0;i<matrix.size();i++)
            min_heap.push(point(matrix[i][0],i,0));
        while(k--)
        {
            res=min_heap.top();
            min_heap.pop();
            if(res.y+1<matrix.size())
                min_heap.push(point(matrix[res.x][res.y+1],res.x,res.y+1));
        }
        return res.val;
    }
};
class Solution2 {
public:
    int kthSmallest(vector<vector<int>>& matrix, int k) {
        priority_queue<int,vector<int>,less<int>> pq;
        for(int i=0;i<matrix.size();i++)
        {
            for(int j=0;j<matrix.size();j++)
            {
                pq.push(matrix[i][j]);
                if(pq.size()>k)
                    pq.pop();
            }
        }
        return pq.top();
    }
};
int main()
{
    Solution1 solute;
    vector<vector<int>> matrix={{1,5,9},{10,11,13},{12,13,15}};
    int k=8;
    cout<<solute.kthSmallest(matrix,k)<<endl;
    return 0;
}

 

 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值