【Garen刷题笔记】 LeetCode 378 有序矩阵中第k小的元素

LeetCode 378 有序矩阵中第k小的元素(7.2日题)

题目:给定一个 n x n 矩阵,其中每行和每列元素均按升序排序,找到矩阵中第 k 小的元素。
请注意,它是排序后的第 k 小元素,而不是第 k 个不同的元素。
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.

示例:
matrix = [
[ 1, 5, 9],
[10, 11, 13],
[12, 13, 15]
],
k = 8,
返回 13。
提示:
你可以假设 k 的值永远是有效的,1 ≤ k ≤ n 2 n^2 n2

解法1
暴力解法,维护一个一维数组,将矩阵进行存储,再排序。
代码

class Solution {
    public int kthSmallest(int[][] matrix, int k) {
        int rows = matrix.length, columns = matrix[0].length;
        int[] sorted = new int[rows * columns];
        int idx = 0;
        for (int[] row : matrix) {
            for (int num : row) {
                sorted[idx++] = num;
            }
        }
        Arrays.sort(sorted);
        return sorted[k - 1];
    }
}

复杂度分析:
时间复杂度: n 2 n^2 n2个数的排序,所以时间复杂度为 O ( n 2 l o g n ) O(n^2logn) O(n2logn)
空间复杂度: n 2 n^2 n2大小的数组,所以空间复杂度为 O ( n 2 ) O(n^2) O(n2)
解法2
优先级队列 + 归并
代码

class Solution {
    public int kthSmallest(int[][] matrix, int k) {
        //Merge + priority queue
        PriorityQueue<int[]> priQueue = new PriorityQueue<>(new Comparator<int[]>(){
            @Override
			public int compare(int[] o1, int[] o2) {
				return o1[0] - o2[0];
            }
        });
        int n = matrix.length, m = matrix[0].length;
        for(int i = 0; i < n; i++){
            priQueue.offer(new int[]{matrix[i][0], i, 0});
        }
        for(int i = 0; i < k - 1; i++){
            int[] cur = priQueue.poll();
            if(cur[2] != m - 1){
                priQueue.offer(new int[]{matrix[cur[1]][cur[2] + 1], cur[1], cur[2] + 1});
            }
        }
        return priQueue.poll()[0];
    }
}

复杂度分析
时间复杂度:归并 k 次,每次堆中插入和弹出的操作时间复杂度均为 l o g n logn logn(因为优先级队列操作就是的操作),所以时间复杂度 O ( k l o g n ) O(klogn) O(klogn)
空间复杂度:堆的大小始终为n,所以空间复杂度为 O ( n ) O(n) O(n)

你可能感兴趣的:(LeetCode刷题笔记)