-
Notifications
You must be signed in to change notification settings - Fork 8
/
Copy path215.kth-largest-element-in-an-array.go
117 lines (106 loc) · 3.05 KB
/
215.kth-largest-element-in-an-array.go
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
/*
* @lc app=leetcode id=215 lang=golang
*
* [215] Kth Largest Element in an Array
*
* https://leetcode.com/problems/kth-largest-element-in-an-array/description/
*
* algorithms
* Medium (47.59%)
* Likes: 1974
* Dislikes: 165
* Total Accepted: 369.1K
* Total Submissions: 774.8K
* Testcase Example: '[3,2,1,5,6,4]\n2'
*
* 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 1:
*
*
* Input: [3,2,1,5,6,4] and k = 2
* Output: 5
*
*
* Example 2:
*
*
* Input: [3,2,3,1,2,4,5,5,6] and k = 4
* Output: 4
*
* Note:
* You may assume k is always valid, 1 ≤ k ≤ array's length.
*
*/
func findKthLargest(nums []int, k int) int {
return QuickSelect(nums, 0, len(nums) - 1, k)
}
// Quick select steps:
// 1. Find a pivot which separates numbers into two parts:
// a. Left: Numbers smaller than pivot.
// b. Right: Numbers larger than pivot.
// 2. Keep repeating Step 1. until we can find a pivot
// which is the kth largest number.
// (i.e. pivot's index == k - 1)
func QuickSelect(arr []int, front int, end int, k int) int {
if len(arr) == 0 || len(arr) < k {
return -1
}
// Only one number in this interval, just return it.
if front == end {
return arr[front]
}
// Find the index of pivot.
pivotIdx := partition(arr, front, end)
// Keep repeating until we find a pivot which is the kth smallest number.
for pivotIdx != k - 1 {
if pivotIdx > k - 1 {
// Pivot is at the right hand side of kth smallest number,
// search left part.
return QuickSelect(arr, front, pivotIdx - 1, k);
} else {
// Pivot is at the left hand side of kth smallest number,
// search right part.
return QuickSelect(arr, pivotIdx + 1, end, k)
}
}
return arr[pivotIdx]
}
func partition(arr []int, front int, end int) int {
// Pivot can be any number in array, we just choose the last number here.
pivot := arr[end]
// i will be the final index of pivot,
// which separates numbers into two parts:
// numbers larger than pivot and numbers smaller than pivot
// i is initialized to: (front - 1) since nothing has been
// compared yet.
i := front - 1
// Compare all numbers (except pivot itself)
// and swap numbers: arr[i+1] and arr[j]
// so that all numbers which are larger than pivot
// will be at the left hand side of all numbers which are
// smaller than pivot.
for j := front; j < end; j++ {
if arr[j] > pivot {
i++
swap(arr, i, j)
}
}
// All numbers except pivot have been compared.
// Now all numbers: arr[front->i] are larger than pivot
// and all numbers: arr[i+1->end-1] are smaller than pivot.
// Swap pivot with the first number which is smaller than pivot (i++)
// so that pivot will be at the position which:
// all numbers at the left hand side of pivot are larger than pivot
// and all numbers at the right hand side of pivot are smaller than pivot.
i++
swap(arr, i, end)
// Return pivot's index.
return i
}
func swap(arr []int, i, j int) {
tmp := arr[i]
arr[i] = arr[j]
arr[j] = tmp
}