二分查找是非常常用的算法,前提是有序序列并且存储在顺序表中,如果是存储方式是链表则不能使用。这里用golang实现一次 ,代码包括四个部分:
1)非递归实现二分查找
2)递归实现二分查找
3)数组有多个重复元素查找目标第一次出现的位置
4)数组有多个重复元素查找目标第最后一次出现的位置
代码如下:
package main import ( "fmt" ) func main() { arr := []int{-1, -1, 2, 2, 4, 4, 7, 7} length := len(arr) m := BinFirst(arr, 0, length-1, 4) //第一次出现的下标 fmt.Println(m) n := BinLast(arr, 0, length-1, 4) //最后一次出现的下标 fmt.Println(n) } //非递归二分查找 //返回查找到的位置,-1表示找不到或错误 //时间复杂度O(logN),空间复杂度O(1) func BinSearch(arr []int, low, high, k int) int { if low < 0 || high < 0 { return -1 } for low <= high { mid := low + (high-low)>>1 if k < arr[mid] { high = mid - 1 } else if k > arr[mid] { low = mid + 1 } else { return mid } } return -1 } //递归二分查找 //时间复杂度O(logN),空间复杂度O(logN) func BinSearch2(arr []int, low, high, k int) int { if low < 0 || high < 0 { return -1 } for low <= high { mid := low + (high-low)>>1 if k < arr[mid] { return BinSearch2(arr, low, mid-1, k) } else if k > arr[mid] { return BinSearch2(arr, mid+1, high, k) } else { return mid } } return -1 } //二分查找返回k第一次出现的下标 func BinFirst(arr []int, low, high, k int) int { if low < 0 || high < 0 { return -1 } for low < high { mid := low + (high-low)>>1 if k > arr[mid] { low = mid + 1 } else { high = mid } } if arr[low] == k { return low } return -1 } //二分查找返回k最后一次出现的下标 func BinLast(arr []int, low, high, k int) int { if low < 0 || high < 0 { return -1 } for low+1 < high { mid := low + (high-low)>>1 if k >= arr[mid] { low = mid } else { high = mid - 1 } } if arr[high] == k { return high } else if arr[low] == k { return low } else { return -1 } }
参考文章:https://blog.csdn.net/daniel_ustc/article/details/17307937