leetcode 378. Kth Smallest Element in a Sorted Matrix

来源:互联网 发布:在ubuntu上下载软件 编辑:程序博客网 时间:2024/05/22 06:28

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大的元素很困难,但是找某个元素A是第几大 则比较容易:从左下角到右上角来遍历查找,得到矩阵中小于等于A的元素个数c,那么A就是第c大。然后用二分查找缩小范围,使c逼近k。

package leetcode;public class Kth_Smallest_Element_in_a_Sorted_Matrix_378 {public int kthSmallest(int[][] matrix, int k) {int n=matrix.length;int low=matrix[0][0];int high=matrix[n-1][n-1];while(low<=high){int mid=(int)(((long)low+(long)high)/2);int count=getLessEqual(matrix, mid);if(count<k){low=mid+1;}else{high=mid-1;}}return low;}//找到某个数在matrix中是第几大public int getLessEqual(int[][] matrix, int val){int count=0;int n=matrix.length;int i=n-1;int j=0;while(i>=0&&j<n){if(matrix[i][j]>val){i--;}else{count=count+(i+1);j++;}}return count;}public static void main(String[] args) {// TODO Auto-generated method stubKth_Smallest_Element_in_a_Sorted_Matrix_378 k=new Kth_Smallest_Element_in_a_Sorted_Matrix_378();int[][] matrix=new int[][]{{2000000000}};System.out.println(k.kthSmallest(matrix, 1));}}

这里有人问:如何保证最终二分查找得到的结果一定是矩阵中的元素呢?就从例子中的矩阵来说吧,low=13,mid=14时,发现count=8>=8,此时hign=mid-1=13,mid=(low+high)/2=13,还是得回到13上来。之后high=mid-1=12,退出循环。

如果矩阵变为
matrix = [
[ 1, 5, 9],
[10, 11, 14],
[12, 14, 15]
]
那么在low=13,mid=14时,同上处理后low=13,high=13,mid回到了13,之后发现count=6<8,还是得low=mid+1=14,然后退出循环。因此最终返回的是low就保证了结果是矩阵中的元素。

有另外的大神考虑用最小堆,也是一个超级好的办法:
1. 首先使用第一行的元素来构建一个最小堆
2. 做下面的步骤 k-1 次:
             每次取出堆顶元素时,需要知道该元素的行数和列数(因此我们可以创建一个tuple类),然后将该元素同列的下一个元素放入堆中。

public class Solution {    public int kthSmallest(int[][] matrix, int k) {        int n = matrix.length;        PriorityQueue<Tuple> pq = new PriorityQueue<Tuple>();        for(int j = 0; j <= n-1; j++) pq.offer(new Tuple(0, j, matrix[0][j]));        for(int i = 0; i < k-1; i++) {            Tuple t = pq.poll();            if(t.x == n-1) continue;//如果拿到的是该列最底部的元素,那么不用管它,继续poll,反正堆里肯定还有元素            pq.offer(new Tuple(t.x+1, t.y, matrix[t.x+1][t.y]));        }        return pq.poll().val;    }}class Tuple implements Comparable<Tuple> {    int x, y, val;    public Tuple (int x, int y, int val) {        this.x = x;        this.y = y;        this.val = val;    }        @Override    public int compareTo (Tuple that) {        return this.val - that.val;    }}

阅读全文
0 0
原创粉丝点击