英文:
Golang Binary search
问题
我正在练习一道面试算法题,现在用Go语言编写代码。目的是练习基本的面试算法,并提升我的Go语言技能。我正在尝试对一个数字数组进行二分查找。
package main
import "fmt"
func main() {
searchField := []int{2, 5, 8, 12, 16, 23, 38, 56, 72, 91}
searchNumber := 23
fmt.Println("Running Program")
fmt.Println("Searching list of numbers: ", searchField)
fmt.Println("Searching for number: ", searchNumber)
numFound := false
//searchCount not working. Belongs in second returned field
result, _ := binarySearch2(searchField, len(searchField), searchNumber, numFound)
fmt.Println("Found! Your number is found in position: ", result)
//fmt.Println("Your search required ", searchCount, " cycles with the Binary method.")
}
func binarySearch2(a []int, field int, search int, numFound bool) (result int, searchCount int) {
//searchCount removed for now.
searchCount, i := 0, 0
for !numFound {
searchCount++
mid := i + (field-i)/2
if search == a[mid] {
numFound = true
result = mid
return result, searchCount
} else if search > a[mid] {
field++
//i = mid + 1 causes a stack overflow
return binarySearch2(a, field, search, numFound)
}
field = mid
return binarySearch2(a, field, search, numFound)
}
return result, searchCount
}
我遇到的主要问题是:
-
当要查找的数字在列表中的位置比中间位置更靠后时,我是否仍在进行二分查找,还是已经转为顺序查找了?我该如何解决这个问题?我已经注释掉了另一种选项,因为它会导致堆栈溢出。
-
我想添加一个步骤计数器,以查看完成搜索需要多少步。这对其他搜索方法也有用。如果我按原样打印搜索计数,它总是显示为1。这是因为我需要返回它(因此在方法的头部调用它)吗?
我知道Go语言有一些可以简化这个过程的方法。我正在努力增加我的知识和编码技能。感谢您的建议。
英文:
I'm practicing an interview algorithm, now coding it in Go. The purpose is to practice basic interview algorithms, and my skills in Go. I'm trying to perform a Binary search of an array of numbers.
package main
import "fmt"
func main() {
searchField := []int{2, 5, 8, 12, 16, 23, 38, 56, 72, 91}
searchNumber := 23
fmt.Println("Running Program")
fmt.Println("Searching list of numbers: ", searchField)
fmt.Println("Searching for number: ", searchNumber)
numFound := false
//searchCount not working. Belongs in second returned field
result, _ := binarySearch2(searchField, len(searchField), searchNumber, numFound)
fmt.Println("Found! Your number is found in position: ", result)
//fmt.Println("Your search required ", searchCount, " cycles with the Binary method.")
}
func binarySearch2(a []int, field int, search int, numFound bool) (result int, searchCount int) {
//searchCount removed for now.
searchCount, i := 0, 0
for !numFound {
searchCount++
mid := i + (field-i)/2
if search == a[mid] {
numFound = true
result = mid
return result, searchCount
} else if search > a[mid] {
field++
//i = mid + 1 causes a stack overflow
return binarySearch2(a, field, search, numFound)
}
field = mid
return binarySearch2(a, field, search, numFound)
}
return result, searchCount
}
The main problems I'm coming across are:
-
When the number is higher in the list than my mid search, am I truly continuing a binary search, or has it turned to a sequential? How can I fix that? The other option I've placed has been commented out because it causes a stack overflow.
-
I wanted to add a step count to see how many steps it takes to finish the search. Something to use with other search methods as well. If I print out the search count as is, it always reads one. Is that because I need to return it (and therefore call for it in the header) in the method?
I understand Go has methods that streamline this process. I'm trying to increase my knowledge and coding skills. I appreciate your input.
答案1
得分: 11
你没有正确地进行二分查找。首先,你的for
循环是无用的,因为条件树中的每个分支都有一个返回语句,所以它永远不会运行多于一次的迭代。看起来你开始以迭代的方式编写代码,然后转换为递归设置,但只是部分地进行了转换。
二分查找的思想是你有一个高位和低位索引,并在它们之间搜索中间点。你没有这样做,你只是增加了field
变量并再次尝试(这将导致你搜索每个索引两次,直到找到该项或通过列表末尾运行而导致段错误)。然而,在Go中,你不需要跟踪高位和低位索引,因为你可以根据需要对搜索字段进行切片。
这是一个更优雅的递归版本:
func binarySearch(a []int, search int) (result int, searchCount int) {
mid := len(a) / 2
switch {
case len(a) == 0:
result = -1 // 未找到
case a[mid] > search:
result, searchCount = binarySearch(a[:mid], search)
case a[mid] < search:
result, searchCount = binarySearch(a[mid+1:], search)
if result >= 0 { // 除了-1(未找到)之外的任何结果
result += mid + 1
}
default: // a[mid] == search
result = mid // 找到
}
searchCount++
return
}
链接:https://play.golang.org/p/UyZ3-14VGB9
英文:
You're not doing a binary search properly. First off, your for
loop is useless, since each branch in the conditional tree has a return statement in it, so it can never run more than one iteration. It looks like you started to code it iteratively, then swapped to a recursive setup, but only kinda halfway converted it.
The idea of a binary search is that you have a high and low index and search the midway point between them. You're not doing that, you're just incrementing the field
variable and trying again (which will cause you to search each index twice until you find the item or segfault by running past the end of the list). In Go, though, you don't need to keep track of the high and low indexes, as you can simply subslice the search field as appropriate.
Here's a more elegant recursive version:
func binarySearch(a []int, search int) (result int, searchCount int) {
mid := len(a) / 2
switch {
case len(a) == 0:
result = -1 // not found
case a[mid] > search:
result, searchCount = binarySearch(a[:mid], search)
case a[mid] < search:
result, searchCount = binarySearch(a[mid+1:], search)
if result >= 0 { // if anything but the -1 "not found" result
result += mid + 1
}
default: // a[mid] == search
result = mid // found
}
searchCount++
return
}
答案2
得分: 5
func BinarySearch(a []int, x int) int {
r := -1 // 未找到
start := 0
end := len(a) - 1
for start <= end {
mid := (start + end) / 2
if a[mid] == x {
r = mid // 找到
break
} else if a[mid] < x {
start = mid + 1
} else if a[mid] > x {
end = mid - 1
}
}
return r
}
这是一个二分查找的函数。给定一个已排序的整数数组 a
和一个目标值 x
,函数会在数组中查找目标值,并返回其索引。如果目标值不存在于数组中,则返回 -1。
英文:
func BinarySearch(a []int, x int) int {
r := -1 // not found
start := 0
end := len(a) - 1
for start <= end {
mid := (start + end) / 2
if a[mid] == x {
r = mid // found
break
} else if a[mid] < x {
start = mid + 1
} else if a[mid] > x {
end = mid - 1
}
}
return r
}
答案3
得分: 2
这是一个离题的问题,但可能会帮助其他寻找简单二分查找的人。
由于标准库没有提供这个常见功能,所以在GitHub上有一个通用的二分查找模块:https://github.com/bbp-brieuc/binarysearch
英文:
Off-topic, but might help others looking for a simple binary search who could land here.
There's a generic binary search module on github since the standard library doesn't offer this common functionality: https://github.com/bbp-brieuc/binarysearch
答案4
得分: 1
func BinarySearch(array []int, target int) int {
startIndex := 0
endIndex := len(array) - 1
midIndex := len(array) / 2
for startIndex <= endIndex {
value := array[midIndex]
if value == target {
return midIndex
}
if value > target {
endIndex = midIndex - 1
midIndex = (startIndex + endIndex) / 2
continue
}
startIndex = midIndex + 1
midIndex = (startIndex + endIndex) / 2
}
return -1
}
这是一个二分查找的函数,它接受一个整数数组和一个目标值作为参数,并返回目标值在数组中的索引。如果目标值不存在于数组中,则返回-1。
英文:
func BinarySearch(array []int, target int) int {
startIndex := 0
endIndex := len(array) - 1
midIndex := len(array) / 2
for startIndex <= endIndex {
value := array[midIndex]
if value == target {
return midIndex
}
if value > target {
endIndex = midIndex - 1
midIndex = (startIndex + endIndex) / 2
continue
}
startIndex = midIndex + 1
midIndex = (startIndex + endIndex) / 2
}
return -1
}
答案5
得分: 0
通用类型版本!(go 1.18)
时间复杂度:log2(n)+1
package main
import "golang.org/x/exp/constraints"
func BinarySearch[T constraints.Ordered](a []T, x T) int {
start, mid, end := 0, 0, len(a)-1
for start <= end {
mid = (start + end) >> 1
switch {
case a[mid] > x:
end = mid - 1
case a[mid] < x:
start = mid + 1
default:
return mid
}
}
return -1
}
带有迭代计数器的完整版本请参见playground。
英文:
generic type version ! (go 1.18)
Time Complexity : log2(n)+1
package main
import "golang.org/x/exp/constraints"
func BinarySearch[T constraints.Ordered](a []T, x T) int {
start, mid, end := 0, 0, len(a)-1
for start <= end {
mid = (start + end) >> 1
switch {
case a[mid] > x:
end = mid - 1
case a[mid] < x:
start = mid + 1
default:
return mid
}
}
return -1
}
full version with iteration counter at playground.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论