Problem
Given an n x n
matrix
where each of the rows and columns is sorted in ascending order, return the kth
smallest element in the matrix.
Note that it is the kth
smallest element in the sorted order, not the kth distinct element.
You must find a solution with a memory complexity better than O(n2)
.
Example 1:
Input: matrix = [[1,5,9],[10,11,13],[12,13,15]], k = 8
Output: 13
Explanation: The elements in the matrix are [1,5,9,10,11,12,13,13,15], and the 8th smallest number is 13
Example 2:
Input: matrix = [[-5]], k = 1
Output: -5
Solution
/**
* @param {number[][]} matrix
* @param {number} k
* @return {number}
*/
var kthSmallest = function(matrix, k) {
const minHeap = Heap((a, b) => a.val - b.val)(
matrix.map((arr, rowIndex) => ({
val: arr[0],
rowIndex,
columnIndex: 0,
})),
)
for (let i = 1; i < k; i++) {
const { rowIndex, columnIndex } = minHeap.extract()
if (matrix[rowIndex][columnIndex + 1] !== undefined) {
minHeap.add({
val: matrix[rowIndex][columnIndex + 1],
rowIndex,
columnIndex: columnIndex + 1,
})
}
}
return minHeap.extract().val
};
const swap = (a, b, arr) => { // eslint-disable-line
if (a !== b) {
const temp = arr[a]
arr[a] = arr[b] // eslint-disable-line
arr[b] = temp // eslint-disable-line
}
}
const Heap = compareFn => (arr = []) => {
const left = index => 2 * index + 1
const right = index => 2 * index + 2
const parent = index => Math.floor((index - 1) / 2)
const size = () => arr.length
// log(n)
const heapify = (index) => {
const l = left(index)
const r = right(index)
let current = index
if ((l < size()) && compareFn(arr[current], arr[l]) > 0) {
current = l
}
if ((r < size()) && compareFn(arr[current], arr[r]) > 0) {
current = r
}
if (current !== index) {
swap(current, index, arr)
heapify(current)
}
}
// log(n)
const heapifyUp = (index) => {
const p = parent(index)
if (p >= 0 && compareFn(arr[p], arr[index]) > 0) {
swap(p, index, arr)
heapifyUp(p)
}
}
// O(n)
const buildHeap = () => {
for (let i = Math.floor(arr.length / 2); i >= 0; i--) {
heapify(i)
}
}
const extract = () => {
swap(0, arr.length - 1, arr)
const top = arr.pop()
heapify(0)
return top
}
const remove = (item) => {
const index = arr.findIndex(x => compareFn(x, item) === 0)
if (index === -1) {
return
}
arr[index] = arr.pop() // eslint-disable-line
const p = parent(index)
if (p < 0 || compareFn(p, arr[index]) < 0) {
heapify(index)
} else {
heapifyUp(index)
}
}
buildHeap()
return {
getHeap: () => arr,
peek: () => {
if (arr.length === 0) {
return null
}
return arr[0]
},
add: (item) => {
arr.push(item)
heapifyUp(arr.length - 1)
},
extract,
remove,
size,
}
}
Complexity:
- Time complexity : O(n).
- Space complexity : O(n).