[LeetCode 378]ソートされたマトリックスのK番目に小さい要素

 行と列のそれぞれが昇順で並べ替えられているn  x  n行列が与えられた  場合、行列のk番目に小さい要素を見つけます。

これは、ソートされた順序でk番目に小さい要素であり、k番目の個別の要素ではないことに注意してください。

例:

行列= [
   [1、5、9]、
   [10、11、13]、
   [12、13、15]
]、
k = 8

戻る13。

 

注:
kは常に有効、1≤k≤n ^ 2と想定できます。

 

ここでの重要な観察は、行と列を別々にソートしたことです。マトリックス全体が上から下、左から右にソートされる必要はありません。与えられた例は意図的に誤解を招くものです。 

 

解決策1.最小ヒープ、O(k * log n)ランタイム、O(n)スペース。

1.最初の行を、値、行、列情報を含む最小ヒープに追加します。

2.最小ヒープから最小値をポーリングし、同じ列に次の値を追加します。これをk回繰り返します。各行がソートされ、各列もソートされるため、マトリックス全体で次に小さい値を常にポーリングすることが保証されます。

 

 

クラスSolution {
     public  int kthSmallest(int [] [] matrix、int k){
         int m = matrix.length、n = matrix [0 ] .length;
        PriorityQueue < int []> minPq = new PriorityQueue <>(Comparator.comparingInt(a- > a [0 ]));
        forint i = 0; i <n; i ++ ){
            minPq.add(new  int [] {m​​atrix [0] [i]、0 、i});
        }
        
        int ans = 0 ;
        while(k> 0 ){
             int [] curr = minPq.poll();
            ans = curr [0 ];
            if(curr [1] <matrix.length-1 ){
                minPq.add(new  int [] {m​​atrix [curr [1] + 1] [curr [2]]、curr [1] + 1、curr [2 ]});
            }
            K - ;
        }
        ansを返します。
    }
}

 

ソリューションのバリエーション1。

上記のソリューションでは、最初の行全体を最初に最小ヒープに追加します。代わりに、matrix [0] [0]のみを追加することを選択できます。次に、最小ヒープからポーリングされる各要素について、その右側にある数とその一番下にある数を追加しようとします。ただし、すでに番号を追加した場合は、追跡するためにO(N ^ 2)の追加のブックキーピングが必要です。 

 

次の例を検討してください。3がポーリングされると、5と7を追加しようとします。6がポーリングされると、7と11を追加しようとします。追跡がない場合、7が2回追加されます。

1 3 5

6 7 12

11 14 14

 

クラスSolution {
     public  int kthSmallest(int [] [] matrix、int k){
        PriorityQueue < int []> minPq = new PriorityQueue <>(Comparator.comparingInt(a- > a [0 ]));
        ブール値 [] []追加= 新しい ブール値 [matrix.length] [matrix [0 ] .length];
        minPq.add(new  int [] {m​​atrix [0] [0]、0、0 });
        追加[ 0] [0] = true ;
        int ans = 0 ;
        while(k> 0 ){
             int [] curr = minPq.poll();
            ans = curr [0 ];
            if(curr [1] <matrix.length-1 &&!added [curr [1] + 1] [curr [2 ]]){
                minPq.add(new  int [] {m​​atrix [curr [1] + 1] [curr [2]]、curr [1] + 1、curr [2 ]});
                追加[curr [ 1] + 1] [curr [2]] = true ;
            }
            if(curr [2] <matrix [0] .length-1 &&!added [curr [1]] [curr [2] + 1 ]){
                minPq.add(new  int [] {m​​atrix [curr [1]] [curr [2] + 1]、curr [1]、curr [2] + 1 });
                追加[curr [ 1]] [curr [2] + 1] = true ;
            }
            K - ;
        }
        ansを返します。
    }
}

 

 

 

ソリューション2.可能な回答範囲のバイナリ検索、O(maxV * N)ランタイム、O(1)スペース。

 

現在の検索範囲の中央値MIDをチェックするたびに、<= MIDである<k個の数値がある場合、[mid + 1、right]で検索します。それ以外の場合は[左、中]で検索します。

 

countSmallerAndEqualメソッドは、O(N)ランタイムであるO(N + N)を取ります。これは、matrix [i] [j]の場合、matrix [k] [j]> = matrix [i] [j]、k> i;となるためです。matrix [i] [k]> = matrix [i] [j]、k> j。

したがって、MID未満の値の総数を検索する場合、jはiが増加した場合にのみ減少する可能性があるため、jをmatrix [0] .length-1にリセットすることは決してありません。 0からn-1に、jをn-1から0に減らします。

 

 

class Solution {
    public int kthSmallest(int[][] matrix, int k) {
        int l = matrix[0][0], r = matrix[matrix.length - 1][matrix[0].length - 1];
        
        while(l < r - 1) {
            int mid = l + (r - l) / 2;
            if(countSmallerAndEqual(matrix, mid) < k) {
                l = mid + 1;
            }
            else {
                r = mid;
            }
        }
        if(countSmallerAndEqual(matrix, l) >= k) {
            return l;
        }
        return r;
    }
    private int countSmallerAndEqual(int[][] matrix, int t) {
        int cnt = 0, j = matrix[0].length - 1;
        for(int i = 0; i < matrix.length; i++) {
            while(j >= 0 && matrix[i][j] > t) {
                j--;
            }
            cnt += j + 1;
        }
        return cnt;
    }
}

 

 

 

 

Related Problems

[LeetCode 287] Find the Duplicate Number

[LeetCode 373] Find K Pairs with Smallest Sums

[LeetCode 719] Find K-th Smallest Pair Distance

おすすめ

転載: www.cnblogs.com/lz87/p/7498510.html