【leetcode】378. Kth Smallest Element in a Sorted Matrix

本文介绍在有序矩阵中寻找第K小元素的方法,包括将所有元素排序及利用最小堆算法。提供C++实现代码。

一、题目描述

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.


题目解读:给出一个矩阵,该矩阵每一行每一列都是从小到大排好序的。找出矩阵中第 k 大的数


方法一:将矩阵中每个元素放入一个数组中,然后对数组进行排序,然后取出第k大的数


c++代码1:使用sort 函数(112ms)

class Solution {
public:
    int kthSmallest(vector<vector<int>>& matrix, int k) {
        int row=matrix.size(); //行
        int col=matrix[0].size();  //列
        vector<int> number;
        for(int i=0; i<row; i++){
            for(int j=0; j<col; j++){
                number.push_back(matrix[i][j]);
            }//for
        }//for
        sort(number.begin(), number.end());
        return number[k-1];
    }
};


c++代码2:使用nth_element函数(52ms)

class Solution {
public:
    int kthSmallest(vector<vector<int>>& matrix, int k) {
        int row=matrix.size(); //行
        int col=matrix[0].size();  //列
        int* number = new int[row*col];
        for(int i=0; i<row; i++){
            for(int j=0; j<col; j++){
                number[i*col+j]=matrix[i][j];
            }//for
        }//for
        nth_element(number, number+k-1, number+(row*col));
        return number[k-1];
    }
};


注意nth_element 函数有个坑,第 k 大的元素是从0开始,因此nth_element里面是 number+k-1 而不是number+k,return返回的也是位置在 k-1 的元素。


方法二:利用矩阵每一行每一列都有序的性质,设置一个最小堆(用priority_queue实现),从左上角的matrix[0][0] 开始,每从堆中取出一个元素就计数count,当count=k时,取出的这个节点的值就是所求,否则当前节点的右边节点和下边节点放入堆中。


此处采用(val, i, j)的形式存储每一个节点,也就是说不仅要存储节点的值,还要存储节点的位置。比如一个节点的位置为i, j,那么该节点的右边节点的位置为 i, j+1, 下边节点是 i+1, j。这里还要注意的一点就是要判断i+1或者j+1有没有超界,并且要判断节点是否已加入过队列了。只有位置没越界并且从来没有加入过队列的节点才能被加入。判断是否加入过队列可以通过设置一个二维数组visited[i][j]来判断位置i,j 的节点是否加入过,没加入过值为0,加入过值为1。


c++代码(132ms)

struct Node{
   int val;  //值
   int x;  //横坐标
   int y;  //竖坐标
   Node(int val, int x, int y):
    val(val), x(x), y(y) {}
	bool operator < (const Node & x)const {
		return val>x.val;
	} 
};

class Solution {
public:
    int kthSmallest(vector<vector<int>>& matrix, int k) {
        int row=matrix.size();  //行数
        int col=matrix[0].size(); //列数
        priority_queue<Node> p;
        int count=0;
        p.push(Node(matrix[0][0], 0, 0));
        int i,j;
        //动态分配一个二维数组来存储已经入队的节点的位置
        int **visited = new int* [row];  //开辟行 
    	for(int i=0; i<row; i++){
    		visited[i] = new int [col];  //开辟列 
    	} //for
    	for(int i=0; i<row; i++){
    		for(int j=0; j<col; j++){
    			visited[i][j]=0;
    		}
    	}
        visited[0][0]=1;
        int result;
        
        while(count<k && !p.empty()){
            count++;
            if(count==k){ 
            	result=p.top().val;
    			break; 
    		} 
            else{
                i=p.top().x;
                j=p.top().y;
                p.pop();
                if((i+1)<row && visited[i+1][j]==0){  //行数 
                	p.push(Node(matrix[i+1][j], i+1, j));
                	visited[i+1][j]=1;
                }  
                if((j+1)<col && visited[i][j+1]==0){//列数
    				p.push(Node(matrix[i][j+1], i, j+1));
    				visited[i][j+1]=1; 
                }
    			 
            }//else
        }//while
        return result;
    }
};





评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值