-
Notifications
You must be signed in to change notification settings - Fork 71
/
No215.kth-largest-element-in-an-array.js
136 lines (118 loc) · 3.13 KB
/
No215.kth-largest-element-in-an-array.js
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
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
/**
* Difficulty:
* Medium
*
* Desc:
* Find the kth largest element in an unsorted array.
* Note that it is the kth largest element in the sorted order, not the kth distinct element.
*
* Example:
* Given [3,2,1,5,6,4] and k = 2, return 5.
*
* Note:
* You may assume k is always valid, 1 ≤ k ≤ array's length.
*
* 求乱序数组中第 K 大的元素。最小堆问题
*/
/**
* ========================================= Solution 1 =========================================
* 最小堆
*/
const buildFromTail = (array) => {
let binaryHeaps = [...array];
for (let i = binaryHeaps.length - 1; i >= 0; i -= 1) {
// 每一个元素作为父元素,和其子元素进行比较
binaryHeaps = sortWithChild(binaryHeaps, i + 1);
}
return binaryHeaps;
};
const less = (num1, num2) => num1 < num2;
const exchange = (arr, i1, i2) => {
const tmp = arr[i1];
arr[i1] = arr[i2];
arr[i2] = tmp;
return arr;
};
const sortWithChild = (heaps, fatherIndex) => {
const childIndexLeft = fatherIndex * 2;
const childIndexRight = childIndexLeft + 1;
if (childIndexLeft > heaps.length) return heaps;
// 如果子元素的大小 < 父元素,则交换位置
if (less(heaps[childIndexLeft - 1], heaps[fatherIndex - 1])) {
heaps = exchange(heaps, childIndexLeft - 1, fatherIndex - 1);
}
if (childIndexRight > heaps.length) return heaps;
if (less(heaps[childIndexRight - 1], heaps[fatherIndex - 1])) {
heaps = exchange(heaps, childIndexRight - 1, fatherIndex - 1);
}
// 将两个子元素作为父元素,继续和它们的子元素进行排序
heaps = sortWithChild(heaps, childIndexLeft);
heaps = sortWithChild(heaps, childIndexRight);
return heaps;
};
/**
* @param {number[]} nums
* @param {number} k
* @return {number}
*/
var findKthLargest_1 = function(nums, k) {
const kItems = nums.slice(0, k);
const heaps = buildFromTail(kItems);
for (let i = k; i < nums.length; i += 1) {
const val = nums[i];
// 如果元素大于堆顶,则交换值,并重新排列堆
if (val > heaps[0]) {
heaps[0] = val;
sortWithChild(heaps, 1);
}
}
return heaps[0];
};
/**
* ========================================= Solution 2 =========================================
* 3-way-partion 三向切分
*/
const partition = (nums, i, k, target) => {
if (i >= k) return i
const swap = (i1, i2) => {
const tmp = nums[i1]
nums[i1] = nums[i2]
nums[i2] = tmp
}
let j = i
while (j <= k) {
if (nums[j] > target) {
swap(j, k)
k -= 1
} else if (nums[j] < target) {
swap(i, j)
i += 1
j += 1
} else {
j += 1
}
}
return i
}
/**
* @param {number[]} nums
* @param {number} k
* @return {number}
*
* 3-way-partion 三向切分
*/
var findKthLargest_2 = function(nums, k) {
let i = 0
let j = nums.length
const getRandomIndex = (i1, i2) => Math.floor(Math.random() * (i2 - i1) + i1)
while (true) {
const mid = getRandomIndex(i, j)
const pivot = partition(nums, i, j - 1, nums[mid])
if (pivot + k === nums.length) return nums[pivot]
if (pivot + k < nums.length) {
i = pivot + 1
} else {
j = pivot
}
}
}