有序矩阵中的第K小的数
日期:2020年7月10日08:46:36
难度:中等
时长:N天(大雾)
分类:暴力、堆、归并、二分
题目:
给定一个 n x n 矩阵,其中每行和每列元素均按升序排序,找到矩阵中第 k 小的元素。
请注意,它是排序后的第 k 小元素,而不是第 k 个不同的元素。
示例:
matrix = [
[ 1, 5, 9],
[10, 11, 13],
[12, 13, 15]
],
k = 8,
返回 13。
解法:
- 降维+sort排序
- 降维+堆排序
- 归并
- 二分
自我尝试——思想错误
我也不知道我在想啥,用了一般的数学找规律,以为是这样的
1 4 9 16 25 然后以为每个正方形是个数值块,右下角的值最大,然后根据K开平方得到所在排和列。。。然后直接排序查找,,,
然而,并不是这样的规律的矩阵
// 自我尝试——思想错误
/**
* @param {number[][]} matrix
* @param {number} k
* @return {number}
*/
var kthSmallest = function (matrix, k) {
if (k <= 1) {
return matrix[0][0];
}
var low = Math.floor(Math.sqrt(k)); // 所在排
console.log(low);
var diff = k - low * low;
console.log(diff);
if (0 == diff) {
return matrix[low - 1][low - 1];
} else {
var row = matrix[low];
var col = [];
for (var i = 0; i < low; i++) {
col.push(matrix[i][low]);
}
// console.log(row);
// console.log(col);
var newArr = Array.prototype.concat(row, col);
newArr.sort(function (a, b) {
return a - b;
});
// console.log(newArr);
return newArr[diff - 1];
}
};
// var matrix = [
// [1, 5, 9],
// [10, 11, 13],
// [12, 13, 15],
// ],
// k = 8;
var matrix = [
[1, 2],
[1, 3],
],
k = 4;
console.log(kthSmallest(matrix, k));
正解
-
降维+sort
//直接排序 var kthSmallest = function (matrix, k) { var arr = []; for (var i = 0; i < matrix.length; i++) { for (var j = 0; j < matrix[i].length; j++) { arr.push(matrix[i][j]); } } arr.sort(function (a, b) { return a - b; }); return arr[k - 1]; };
-
降维+最大堆
siftdown
首先判断节点的左子节点是否存在,然后和左子节点进行比较,得到较大的再和右子节点比较,得到子树中最大的,然后进行交换。继续判断其子树直到没子树// 拆解矩阵 + 最大堆( /** * @param {number[][]} matrix * @param {number} k * @return {number} */ var kthSmallest = function (matrix, k) { function Heap(arr) { this.heap = arr || []; return this.init(); } Heap.prototype = { constructor: Heap, init: function () { this.len = this.heap.length; // console.log(this.heap); if (this.len == 0) { throw Error("数据为空"); } }, get() { return this.heap; }, peekHead: function () { return this.heap[0]; }, replaceHead: function (num) { this.heap[0] = num; return this.heap; }, getMaxHeap: function () { for (let i = Math.floor(this.len / 2); i >= 0; i--) { // console.log("根节点", this.heap[i]); this.siftDown(i); } return this.heap; }, siftDown: function (i) { var flag = false; var t = i; // 节点循环 // console.log("被优化的", this.heap[i]); while (i * 2 < this.len && !flag) { // 左子节点判断 if (this.heap[i] < this.heap[i * 2]) { t = i * 2; } else { t = i; } // 右子节点判断 if (i * 2 + 1 < this.len) { if (this.heap[t] < this.heap[i * 2 + 1]) { t = i * 2 + 1; } // else { // t = i; // } } if (t == i) { flag = true; } else { var temp = this.heap[i]; this.heap[i] = this.heap[t]; this.heap[t] = temp; i = t; } } }, }; // 降维 var arr = []; for (var i = 0; i < matrix.length; i++) { arr.push(...matrix[i]); } // 创建最大堆 var heap = new Heap(arr.slice(0, k)); heap.getMaxHeap(); // console.log(heap); for (var j = k; j < arr.length; j++) { // console.log(arr[j], heap.peekHead()); if (arr[j] <= heap.peekHead()) { heap.replaceHead(arr[j]); heap.siftDown(0); } } // console.log(heap); return heap.peekHead(); }; var matrix = [ [1, 5, 9], [10, 11, 13], [12, 13, 15], ], k = 8; var matrix = [ [1, 2], [1, 3], ], k = 2; var matrix = [ [1, 3, 5], [6, 7, 12], [11, 14, 14], ], k = 5; console.log(kthSmallest(matrix, k));
-
归并