leetcode378. Kth Smallest Element in a Sorted Matrix

題目要求

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個數字,這裏須要注意,不要求必定要是惟一的值,即假設存在這樣一個序列1,2,2,3,則第三個數字是2而不是3。java

思路一:優先隊列

當涉及到從一個集合中查找一個元素這樣的問題時,咱們每每會馬上想到查找的幾種方式:有序數組查找,無序數組查找,堆排序。這裏若是將二維數組轉化爲一維有序數組,成本未免太大了。同理,將其中全部元素都轉化爲堆,也會存在內存不足的問題。所以咱們能夠採用部分元素堆排序便可。即咱們每次只須要可能構成第k個元素的值進行堆排序就能夠了。數組

public int kthSmallest(int[][] matrix, int k) {
        //優先隊列
        PriorityQueue<Tuple> queue = new PriorityQueue<Tuple>();
        //將每一行的第一個元素放入優先隊列中
        for(int i = 0 ; i<matrix.length ; i++) {
            queue.offer(new Tuple(i, 0, matrix[i][0]));
        }
        
        //對優先隊列執行k次取操做,取出來的就是第k個值
        for(int i = 0 ; i<k-1 ; i++) {
            Tuple t = queue.poll();
            //判斷是否到達行尾,若沒有,則將下一個元素做爲潛在的第k個元素加入優先隊列中
            if(t.y == matrix[0].length-1) continue;
            queue.offer(new Tuple(t.x, t.y+1, matrix[t.x][t.y+1]));
        }
        return queue.poll().value;
    }
    
    /**
    * 存儲矩陣中x,y和該下標上對應的值的Tuple
    */
    public static class Tuple implements Comparable<Tuple>{
        int x;
        int y;
        int value;
        
        public Tuple(int x, int y, int value) {
            this.x = x;
            this.y = y;
            this.value = value;
        }
        @Override
        public int compareTo(Tuple o) {
            // TODO Auto-generated method stub
            return this.value - o.value;
        }
    }

思路二:二分法查找

二分查找的核心問題在於,如何找到查找的上界和下屆。這邊咱們能夠矩陣中的最大值和最小值做爲上界和下界。而後不停的與中間值進行比較,判斷當前矩陣中小於該中間值的元素有幾個,若是數量不足k,就將左指針右移,不然,就將右指針左移。直到左右指針相遇。這裏須要注意,不能在數量等於k的時候就返回mid值,由於mid值不必定在矩陣中存在。ide

public int kthSmallest2(int[][] matrix, int k){
        int low = matrix[0][0], high = matrix[matrix.length-1][matrix[0].length-1];
        while(low <= high) {
            int mid = low + (high - low) / 2;
            int count = 0;
            int i = matrix.length-1 , j = 0;
            //自矩陣左下角開始計算比mid小的數字的個數
            while(i>=0 && j < matrix.length){
                if(matrix[i][j]>mid) i--;
                else{
                    count+=i+1;
                    j++;
                }
            }
            if(count < k) {
                low = mid + 1;
            }else{
                high = mid - 1;
            }
        }
        return low;
    }
相關文章
相關標籤/搜索