-
Notifications
You must be signed in to change notification settings - Fork 31
/
HeapSort.ts
82 lines (70 loc) · 2.11 KB
/
HeapSort.ts
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
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
// HeapSort 堆排序
// 防止快速排序退化时,可以使用堆排序
type Mutable<T> = { -readonly [P in keyof T]: T[P] }
function heapSort<T>(
arr: Mutable<ArrayLike<T>>,
compareFn: (a: T, b: T) => number,
start = 0,
end = arr.length
): void {
if (start < 0) start = 0
if (end > arr.length) end = arr.length
if (start >= end) return
const first = start
const lo = 0
const hi = end - start
// Build heap with greatest element at top.
for (let i = (hi - 1) >>> 1; ~i; i--) {
pushDown(i, hi, first)
}
// Pop elements, largest first, into end of data.
for (let i = hi - 1; ~i; i--) {
const tmp = arr[first]
arr[first] = arr[first + i]
arr[first + i] = tmp
pushDown(lo, i, first)
}
// pushDown implements the heap property on arr[lo:hi].
// first is an offset into the array where the root of the heap lies.
function pushDown(lo: number, hi: number, offset: number): void {
let root = lo
while (true) {
let child = (root << 1) | 1
if (child >= hi) {
break
}
if (child + 1 < hi && compareFn(arr[offset + child], arr[offset + child + 1]) < 0) {
child++
}
if (compareFn(arr[offset + root], arr[offset + child]) >= 0) {
return
}
const tmp = arr[offset + root]
arr[offset + root] = arr[offset + child]
arr[offset + child] = tmp
root = child
}
}
}
export {}
if (require.main === module) {
const arr = [4, 2, 100, 99, 10000, -1, 99, 2]
heapSort(arr, (a, b) => a - b)
console.log(arr)
// https://leetcode.cn/problems/the-k-strongest-values-in-an-array/
// eslint-disable-next-line no-inner-declarations
function getStrongest(arr: number[], k: number): number[] {
arr.sort((a, b) => a - b)
heapSort(arr, (a, b) => a - b)
const m = arr[(arr.length - 1) >> 1]
heapSort(arr, (a, b) => {
const diffA = Math.abs(a - m)
const diffB = Math.abs(b - m)
if (diffA === diffB) {
return b - a
}
return diffB - diffA
})
return arr.slice(0, k)
}
}