算法inGo:BinarySearch(二分查找)BinarySearch(二分查找)BinarySearch(二分查找)猜数1、2、3、4、5、6、7、8排好序一个集合,先从中间开始猜,根据提示就可以排除一半,在剩余的一半里,再从中间开始猜,依此类推,这就是二分查找。Bi
创建项目
~/Code/go via 🐹 v1.20.3 via 🅒 base ➜ mcd algorithms_binary_search Code/go/algorithms_binary_search via 🐹 v1.20.3 via 🅒 base ➜ go mod init algorithms_binary_search go: creating new go.mod: module algorithms_binary_search Code/go/algorithms_binary_search via 🐹 v1.20.3 via 🅒 base ➜ c Code/go/algorithms_binary_search via 🐹 v1.20.3 via 🅒 base ➜
这段代码r := rand.New(rand.NewSource(time.Now().UnixNano())) v := r.Intn(10)
和这段代码:v := rand.Intn(10)
有什么区别?
这两段代码的区别在于随机数生成器的种子(seed)。
在第一段代码中,我们使用了 rand.NewSource(time.Now().UnixNano())
作为种子,创建了一个新的随机数生成器 r
。time.Now().UnixNano()
返回当前时间的纳秒表示,作为种子值。通过使用不同的种子值,我们可以得到不同的随机数序列。
然后,我们使用 r.Intn(10)
从生成器 r
中生成一个介于 0 和 9 之间的随机整数。
而在第二段代码中,我们直接调用了 rand.Intn(10)
,这里的 rand
是 Go 语言中的标准库 math/rand
包,它使用默认的随机数生成器。默认情况下,标准库的随机数生成器的种子值是固定的(通常为 1),因此在相同的程序运行中多次调用 rand.Intn(10)
得到的随机数序列是相同的。
因此,第一段代码使用了一个可变的种子值,每次运行程序时都会产生不同的随机数序列,而第二段代码使用了固定的种子值,多次运行得到的随机数序列是相同的。

package main
import (
"fmt"
"math/rand"
"time"
)
func main() {
list := make([]int, 1_000_000)
for i := 0; i < 1_000_000; i++ {
list = append(list, i+1)
}
// rand.Seed(time.Now().UnixNano())
r := rand.New(rand.NewSource(time.Now().UnixNano()))
for i := 0; i < 20; i++ {
v := r.Intn(1_000_000-1) + 1
fmt.Printf("针对 %d 进行二分查找:\n", v)
idx := binarySearch(list, v)
fmt.Printf("%d 的索引位置是:[%d]\n", v, idx)
fmt.Println("_____________________________")
}
}
func binarySearch(list []int, target int) int {
low := 0
high := len(list) - 1
step := 0
for {
step = step + 1
if low <= high {
mid := (low + high) / 2
guess := list[mid]
if guess == target {
fmt.Printf("共查找了 %d 次\n", step)
return mid
}
if guess > target {
high = mid - 1
} else {
low = mid + 1
}
}
}
}
运行
Code/go/algorithms_binary_search via 🐹 v1.20.3 via 🅒 base ➜ go run . 针对 518758 进行二分查找: 共查找了 21 次 518758 的索引位置是:[1518757] _____________________________ 针对 13067 进行二分查找: 共查找了 18 次 13067 的索引位置是:[1013066] _____________________________ 针对 186102 进行二分查找: 共查找了 18 次 186102 的索引位置是:[1186101] _____________________________ 针对 606006 进行二分查找: 共查找了 21 次 606006 的索引位置是:[1606005] _____________________________ 针对 806929 进行二分查找: 共查找了 17 次 806929 的索引位置是:[1806928] _____________________________ 针对 938525 进行二分查找: 共查找了 19 次 938525 的索引位置是:[1938524] _____________________________ 针对 718792 进行二分查找: 共查找了 21 次 718792 的索引位置是:[1718791] _____________________________ 针对 583982 进行二分查找: 共查找了 20 次 583982 的索引位置是:[1583981] _____________________________ 针对 569047 进行二分查找: 共查找了 21 次 569047 的索引位置是:[1569046] _____________________________ 针对 450770 进行二分查找: 共查找了 21 次 450770 的索引位置是:[1450769] _____________________________ 针对 503611 进行二分查找: 共查找了 19 次 503611 的索引位置是:[1503610] _____________________________ 针对 792959 进行二分查找: 共查找了 21 次 792959 的索引位置是:[1792958] _____________________________ 针对 663440 进行二分查找: 共查找了 21 次 663440 的索引位置是:[1663439] _____________________________ 针对 967010 进行二分查找: 共查找了 20 次 967010 的索引位置是:[1967009] _____________________________ 针对 631813 进行二分查找: 共查找了 20 次 631813 的索引位置是:[1631812] _____________________________ 针对 608258 进行二分查找: 共查找了 21 次 608258 的索引位置是:[1608257] _____________________________ 针对 494806 进行二分查找: 共查找了 21 次 494806 的索引位置是:[1494805] _____________________________ 针对 92081 进行二分查找: 共查找了 19 次 92081 的索引位置是:[1092080] _____________________________ 针对 615060 进行二分查找: 共查找了 21 次 615060 的索引位置是:[1615059] _____________________________ 针对 798577 进行二分查找: 共查找了 20 次 798577 的索引位置是:[1798576] _____________________________ Code/go/algorithms_binary_search via 🐹 v1.20.3 via 🅒 base ➜
log2^1_000_000 的对数大约等于19.93,所以说最多的次数应该是20次才对,为什么会有这么多21次?
因为二分查找取中间数,有可能不在正中间的位置,就有可能多出来一次,比如1 2 3 4 这个集合。
要计算以 2 为底的 100 万的对数,可以使用对数的换底公式。
换底公式为:log_b(x) = log_c(x) / log_c(b)
在这个问题中,我们需要计算以 2 为底的 100 万的对数,可以将其转换为以 10 为底的对数:
log_2(1000000) = log_10(1000000) / log_10(2)
现在我们可以使用任何对数计算器或编程语言中的对数函数来计算这个表达式。在这里,我们将使用自然对数(以 e 为底)来计算它。
log_2(1000000) ≈ ln(1000000) / ln(2)
让我计算一下:

package main
import (
"fmt"
"math"
)
func main() {
result := math.Log(1000000) / math.Log(2)
fmt.Println(result)
}
输出结果大约为 19.931568569324174。
因此,以 2 为底的 100 万的对数约为 19.93。
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!