forked from chen3feng/stl4go
-
Notifications
You must be signed in to change notification settings - Fork 0
/
binary_search.go
121 lines (115 loc) · 2.91 KB
/
binary_search.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
118
119
120
121
package stl4go
// LowerBound returns an index to the first element in the ascending ordered slice a that
// does not satisfy element < value (i.e. greater or equal to),
// or len(a) if no such element is found.
//
// Complexity: O(log(len(a))).
func LowerBound[T Ordered](a []T, value T) int {
loc := 0
count := len(a)
for count > 0 {
i := loc
step := count / 2
i += step
if a[i] < value {
i++
loc = i
count -= step + 1
} else {
count = step
}
}
return loc
}
// LowerBoundFunc returns an index to the first element in the ordered slice a that
// does not satisfy less(element, value)), or len(a) if no such element is found.
//
// The elements in the slice a should sorted according with compare func less.
//
// Complexity: O(log(len(a))).
func LowerBoundFunc[T any](a []T, value T, less LessFn[T]) int {
loc := 0
count := len(a)
for count > 0 {
i := loc
step := count / 2
i += step
if less(a[i], value) {
i++
loc = i
count -= step + 1
} else {
count = step
}
}
return loc
}
// UpperBound returns an index to the first element in the ascending ordered slice a such that
// value < element (i.e. strictly greater), or len(a) if no such element is found.
//
// Complexity: O(log(len(a))).
func UpperBound[T Ordered](a []T, value T) int {
loc := 0
count := len(a)
for count > 0 {
i := loc
step := count / 2
i += step
if !(value < a[i]) {
i++
loc = i
count -= step + 1
} else {
count = step
}
}
return loc
}
// UpperBoundFunc returns an index to the first element in the ordered slice a such that
// less(value, element)) is true (i.e. strictly greater), or len(a) if no such element is found.
//
// The elements in the slice a should sorted according with compare func less.
//
// Complexity: O(log(len(a))).
func UpperBoundFunc[T any](a []T, value T, less LessFn[T]) int {
loc := 0
count := len(a)
for count > 0 {
i := loc
step := count / 2
i += step
if !less(value, a[i]) {
i++
loc = i
count -= step + 1
} else {
count = step
}
}
return loc
}
// BinarySearch returns the (index, true) to the first element in the ascending ordered slice a
// such that element == value, or (-1, false) if no such element is found.
//
// Complexity: O(log(len(a))).
func BinarySearch[T Ordered](a []T, value T) (index int, ok bool) {
loc := LowerBound(a, value)
if loc < len(a) && a[loc] == value {
return loc, true
}
return -1, false
}
// BinarySearchFunc returns the (index, true) to the first element in the ordered slice a such that
// less(element, value) and less(value, element) are both false,
// or (-1, false) if no such element is found.
//
// The elements in the slice a should sorted according with compare func less.
//
// Complexity: O(log(len(a))).
func BinarySearchFunc[T any](a []T, value T, less LessFn[T]) (index int, ok bool) {
loc := LowerBoundFunc(a, value, less)
if loc < len(a) && !less(value, a[loc]) {
return loc, true
}
return -1, false
}