比如查找一个数组var arr = []int{10, 5, 6, 19, 35, 24, 17, 5, 5, 5, 5, 5, 5, 5}里面5出现的起始位置和终止位置
1:直接遍历,时间复杂度为O(N)
如果是排序好的数组 5 5 5 5 5 5 5 5 6 10 17 19 24 35
2:可以先二分查找到5,再向两边扩散,扩算的时候可以继续二分
package main
import (
"fmt"
"sort"
)
func find(arr []int, el int) (first, last int) {
left := 0
right := len(arr) - 1
middle := middle_find(arr, left, right, el)
if middle == -1 {
return -2, -2
}
first = middle_find(arr, left, middle-1, el) //middle=-1就越界了
last = middle_find(arr, middle+1, right, el)
tmpfirst, tmplast := first, last
//二分向两边扩散
for {
if first == -1 {
first = tmpfirst
break
}
if first <= left {
break
}
tmpfirst = first
first = middle_find(arr, left, first-1, el) //二分偏移量最少,并且是单边二分,往小的方向
}
for {
if last == -1 {
last = tmplast
break
}
if last >= right {
break
}
tmplast = last
last = middle_find(arr, last+1, right, el) //单边二分,往大的方向
}
if first == -1 && middle != -1 {
first = middle
}
if last == -1 && middle != -1 {
last = middle
}
return first, last
}
//二分查找
func middle_find(arr []int, left, right int, el int) int {
middle := (left + right) / 2
for left < right-1 { //注意是right-1,left=0,right=1,middle=(left+right)/2=0 不然会导致死循环
if arr[middle] < el {
left = middle
middle = (left + right) / 2
}
if arr[middle] > el {
right = middle
middle = (left + right) / 2
}
if arr[middle] == el {
return middle
}
}
if arr[right] == el {
return left
} else {
return -1
}
}
func show_arr(arr []int) {
len1 := len(arr)
for i := 0; i < len1; i++ {
fmt.Printf("%d ", arr[i])
}
fmt.Printf("\n")
}
func main() {
var arr = []int{10, 5, 6, 19, 35, 24, 17, 5, 5, 5, 5, 5, 5, 5}
sort.Ints(arr)
first, last := find(arr, 5)
fmt.Printf("search the value %d: first index %d,last index %d \n", 5, first+1, last+1)
show_arr(arr)
}
输出:
search the value 5: first index 1,last index 8
5 5 5 5 5 5 5 5 6 10 17 19 24 35