Перейти ошибка двоичного поиска
Предположим, у вас есть два варианта использования:
a := [] int {2, 2, 3, 4}
i := sort.Search(len(a), func(pos int) bool { return a[pos] == 2})
fmt.Printf("%v -> %v \n", a, i)
b := [] int {1, 2, 2, 3, 4}
j := sort.Search(len(b), func(pos int) bool { return b[pos] == 2})
fmt.Printf("%v -> %v \n", b, j)
Ответ для тех:
[2 2 3 4] -> 4
[1 2 2 3 4] -> 1
Я полагаю, это должно быть 1
в обоих случаях нет? Кто-нибудь знает почему?
1 ответ
sort.Search()
возвращает наименьший индекс i
в [0, n)
в котором f(i)
является true
,
Поскольку индексы срезов основаны на 0, следует ожидать возврата 0
для первого и 1
для второго. Это (похоже) работает для второго.
Цитата из документа:
... при условии, что в диапазоне [0, n),
f(i) == true
подразумеваетf(i+1) == true
, То есть поиск требует, чтобыf
являетсяfalse
для некоторого (возможно, пустого) префикса входного диапазона [0, n), а затемtrue
для (возможно, пустого) остатка; Поиск возвращает первыйtrue
индекс. Если такого индекса нет, Search возвращаетn
,
Ваша функция не соответствует критериям sort.Search()
надеется. Ваша функция состоит не в том, чтобы сказать, является ли элемент по указанному индексу тем, который вы ищете, а в том, чтобы сказать:
- если элемент по запрошенному индексу равен или больше (возврат
true
) - или если элемент по указанному индексу меньше искомого (возврат
false
).
(Бинарный поиск не может быть выполнен, если вы скажете только, когда они равны, но не когда они больше или меньше.)
Так что просто используйте >=
сравнение вместо ==
, Правильное использование:
a := []int{2, 2, 3, 4}
i := sort.Search(len(a), func(pos int) bool { return a[pos] >= 2 })
fmt.Printf("%v -> %v \n", a, i)
b := []int{1, 2, 2, 3, 4}
j := sort.Search(len(b), func(pos int) bool { return b[pos] >= 2 })
fmt.Printf("%v -> %v \n", b, j)
Вывод (попробуйте на Go Playground):
[2 2 3 4] -> 0
[1 2 2 3 4] -> 1
Примечание: также из документа:
Например, учитывая данные среза, отсортированные в порядке возрастания, вызов
Search(len(data), func(i int) bool { return data[i] >= 23 })
возвращает наименьший индекс
i
такой, чтоdata[i] >= 23
, Если звонящий хочет узнать,23
находится в срезе, его надо проверитьdata[i] == 23
по отдельности.
Более простая альтернатива: sort.SearchInts()
Если вы хотите найти int
значение в int
ломтик ([]int
), просто используйте sort.SearchInts()
:
a := []int{2, 2, 3, 4}
i := sort.SearchInts(a, 2)
fmt.Printf("%v -> %v \n", a, i)
b := []int{1, 2, 2, 3, 4}
j := sort.SearchInts(b, 2)
fmt.Printf("%v -> %v \n", b, j)
Вывод (попробуйте на Go Playground):
[2 2 3 4] -> 0
[1 2 2 3 4] -> 1