题目
给你一个 n x n 矩阵 matrix ,其中每行和每列元素均按升序排序,找到矩阵中第 k 小的元素。
请注意,它是 排序后 的第 k 小元素,而不是第 k 个 不同 的元素。
你必须找到一个内存复杂度优于 O(n2) 的解决方案。
示例 1:
1 2 3
| 输入:matrix = [[1,5,9],[10,11,13],[12,13,15]], k = 8 输出:13 解释:矩阵中的元素为 [1,5,9,10,11,12,13,13,15],第 8 小元素是 13
|
示例 2:
1 2
| 输入:matrix = [[-5]], k = 1 输出:-5
|
提示:
n == matrix.length
n == matrix[i].length
1 <= n <= 300
-109 <= matrix[i][j] <= 109
- 题目数据 保证
matrix 中的所有行和列都按 非递减顺序 排列
1 <= k <= n2
实现代码
方式一
分治算法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
| class Solution { public int kthSmallest(int[][] matrix, int k) {
int[] mergeArray = kthSmallest(matrix, 0, matrix.length - 1); return mergeArray[k-1]; }
public int[] kthSmallest(int[][] matrix, int left, int right) {
if (left == right) { return matrix[left]; } int mid = left + (right - left) / 2; int[] leftArray = kthSmallest(matrix, left, mid); int[] rightArray = kthSmallest(matrix, mid + 1, right); return merge(leftArray, rightArray); }
private int[] merge(int[] array1, int[] array2) {
int[] newArray = new int[array1.length + array2.length]; int k = 0; int j = 0; int n = 0; while (array1.length != k && array2.length != j) { if (array1[k] < array2[j]) { newArray[n] = array1[k]; k++; n++; } else { newArray[n] = array2[j]; j++; n++; } } if (array1.length != k){ for (int i = k; i < array1.length; i++) { newArray[n] = array1[i]; n++; } } if (array2.length != j){ for (int i = j; i < array2.length; i++) { newArray[n] = array2[i]; n++; } } return newArray; } }
|
时间复杂度
时间组成:
空间复杂度
方式二
优先级队列
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| class Solution { public int kthSmallest(int[][] matrix, int k) { PriorityQueue<int[]> pq = new PriorityQueue<>((a, b) -> { return a[0] - b[0]; }); for (int i = 0; i < matrix.length; i++) { pq.offer(new int[] { matrix[i][0], i, 0 }); } int[] poll; while (!pq.isEmpty() && k > 0) { poll = pq.poll(); k--; if (k == 0) { return poll[0]; } int nextIndex = poll[2] + 1; if (nextIndex < matrix.length) { pq.offer(new int[] { matrix[poll[1]][nextIndex], poll[1], nextIndex }); } } return 0; } }
|
核心难点在于如何定义优先队列的元素,因为数组不像链表那样有记录下一个的指针,所以构建的元素需要额外的空间进行存储
时间复杂度
时间组成:
- 初始化堆:假设
matrix的长度为n,总共O(n*logn)
while循环:poll+offer = O(logn),总共O(k*logn)
总时间复杂度:O(nlogn) + O(klogn) = O((n + k)logn)
空间复杂度
空间组成:
总空间复杂度:O(n)