-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathrSelect.go
60 lines (47 loc) · 1.36 KB
/
rSelect.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
package main
import (
"fmt"
"math/rand"
)
func rSelect(elements []int, statistic int) int { // todo how do we treat even/odd lengths? Which way is perfered?
if len(elements) == 1 { // base case
return elements[0]
}
leftpoint, rightpoint := 0, len(elements)-1
pivot := rand.Intn(rightpoint)
boundary := swapAroundPivot(elements, pivot, leftpoint, rightpoint)
if boundary == statistic { // really lucky
return elements[boundary]
} else if boundary > statistic {
if split := boundary - 1; split > 0 {
return rSelect(elements[:split], statistic)
}
}
return rSelect(elements[boundary:], statistic-boundary)
}
func swapAroundPivot(elements []int, pivotIndx, leftpoint, rightpoint int) int {
if pivotIndx != leftpoint {
elements[leftpoint], elements[pivotIndx] = elements[pivotIndx], elements[leftpoint]
pivotIndx = leftpoint
}
pivot := elements[pivotIndx]
i := leftpoint + 1
for j := range elements {
if j > 0 {
if elements[j] < pivot { // the only case when anything needs to happen
elements[j], elements[i] = elements[i], elements[j]
i++
}
}
}
// swap the pivot element into place
elements[pivotIndx], elements[i-1] = elements[i-1], elements[pivotIndx]
return i
}
func main() {
test := []int{1, 2, 3, 4, 5}
res := rSelect(test, 3)
fmt.Println(res)
nextTry := rSelect([]int{1, 2, 3, 4, 5, 6, 7, 9, 8}, 5)
fmt.Println(nextTry)
}