Golang二进制搜索

时间:2017-03-28 15:27:01

标签: go 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)当列表中的数字高于我的中搜索时,我真的继续进行二分搜索,还是转为顺序搜索?我该如何解决这个问题?我放置的另一个选项已被注释掉,因为它会导致堆栈溢出。

2)我想添加一个步数来查看完成搜索所需的步骤数。也可以与其他搜索方法一起使用。如果我按原样打印搜索计数,它总是读取一个。那是因为我需要在方法中返回它(因此在标题中调用它)吗?

我理解Go有简化此过程的方法。我正在努力提高自己的知识和编码技巧。感谢您的投入。

3 个答案:

答案 0 :(得分:6)

您没有正确进行二进制搜索。首先,你的for循环是无用的,因为条件树中的每个分支都有一个return语句,因此它永远不会运行多次迭代。看起来你开始迭代编码,然后交换到递归设置,但只有一半转换它。

二进制搜索的想法是你有一个高低索引并搜索它们之间的中间点。你没有这样做,你只是递增field变量并再次尝试(这将导致你搜索每个索引两次,直到你通过运行列表的末尾找到项目或段错误)。但是,在Go中,您不需要跟踪高低索引,因为您可以根据需要简单地对搜索字段进行切换。

这是一个更优雅的递归版本:

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)
        result += mid + 1
    default: // a[mid] == search
        result = mid // found
    }
    searchCount++
    return
}

https://play.golang.org/p/4zLgX-_0ZS

答案 1 :(得分:0)

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
}

答案 2 :(得分:0)

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
}