-
Notifications
You must be signed in to change notification settings - Fork 0
/
ints.go
101 lines (93 loc) · 1.89 KB
/
ints.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
package util
import "sort"
// Sort3 returns the given three integers sorted by value (smallest first).
func Sort3(x, y, z int) (a, b, c int) {
if x <= y { // x <= y
if x <= z { // x <= y, x <= z
if y <= z { // x <= y, x <= z, y <= z
return x, y, z
} else { // x <= y, x <= z, y > z
return x, z, y
}
} else { // x <= y, x > z
return z, x, y
}
} else { // x > y
if y <= z { // x > y, y <= z
if x <= z { // x > y, y <= z, x <= z
return y, x, z
} else { // x > y, y <= z, x > z
return y, z, x
}
} else { // x > y, y > z
return z, y, x
}
}
}
// QuickSelect returns the k'th smallest element of the input array.
func QuickSelect(input []int, k int) int {
const cutoff = 12
origInput := true
next := []int(nil)
for len(input) > cutoff {
if origInput {
origInput = false
input = append([]int(nil), input...)
next = make([]int, len(input))
}
_, pivot, _ := Sort3(input[0], input[len(input)/2], input[len(input)-1])
lt, gt := 0, 0
for _, n := range input {
switch {
case n < pivot:
next[lt] = n
lt++
case n > pivot:
next[len(next)-1-gt] = n
gt++
}
}
switch {
case k < lt:
input, next = next[:lt], input[:lt]
case k >= len(input)-gt:
input, next, k = next[len(input)-gt:], input[len(input)-gt:], k-(len(input)-gt)
default:
return pivot
}
}
if len(input) == 1 {
return input[0]
} else if len(input) == 2 {
if k == 0 {
if input[0] <= input[1] {
return input[0]
} else {
return input[1]
}
} else {
if input[0] <= input[1] {
return input[0]
} else {
return input[1]
}
}
} else if len(input) == 3 {
a, b, c := Sort3(input[0], input[1], input[2])
switch k {
case 0:
return a
case 1:
return b
default:
return c
}
}
if origInput {
var tmp [cutoff]int
copy(tmp[:len(input)], input)
input = tmp[:len(input)]
}
sort.Ints(input)
return input[k]
}