写在前面:本文侧重诠释对算法的思考记录过程,忽略其他诸如代码简洁、字符编码等细节问题。
package main
//二分查找算法,针对的是一个有序的数据集合,每次都通过跟区间的中间元素对比,
//将待查找的区间缩小为之前的一半,直到找到要查找的元素,或者区间被缩小为0为止
//时间复杂度:O(logn)
func Divide2Select(nums []int, target int) int {
return DivideSelect(nums, target, 0, len(nums)-1)
}
func DivideSelect(nums []int, target, start, end int) int {
if start > end {
return -1
}
middle := (start + end) / 2
if target < nums[middle] {
return DivideSelect(nums, target, 0, middle-1)
} else if target > nums[middle] {
return DivideSelect(nums, target, middle+1, end)
} else {
return middle
}
}
//二分法查找的变形版本:在一个给定排序序列中查找第一个等于给定值的元素
//(待查找的元素在序列中有多个)
func Divide2SelectFirst(nums []int, target int) int {
return DivideSelectFirst(nums, target, 0, len(nums)-1)
}
func DivideSelectFirst(nums []int, target, start, end int) int {
if start > end {
return -1
}
middle := (start + end) / 2
if target < nums[middle] {
return DivideSelectFirst(nums, target, 0, middle-1)
} else if target > nums[middle] {
return DivideSelectFirst(nums, target, middle+1, end)
} else {
if middle == 0 || nums[middle-1] != target {
return middle
} else {
return DivideSelectFirst(nums, target, 0, middle-1)
}
}
}
//二分法查找的变形版本:在给定已排序序列中查找最后一个等于给定值的元素
//(待查找的元素在序列中有多个)
func Divide2SelectLast(nums []int, target int) int {
return DivideSelectLast(nums, target, 0, len(nums)-1)
}
func DivideSelectLast(nums []int, target, start, end int) int {
if start > end {
return -1
}
middle := (start + end) / 2
if target < nums[middle] {
return DivideSelectLast(nums, target, 0, middle-1)
} else if target > nums[middle] {
return DivideSelectLast(nums, target, middle+1, end)
} else {
if middle == len(nums)-1 || nums[middle+1] != target {
return middle
} else {
return DivideSelectLast(nums, target, middle+1, end)
}
}
}
//二分法查找的变形版本:在给定排序序列中查找第一个大于等于给定值的元素
func Divide2SelectLargeFirst(nums []int, target int) int {
return DivideSelectLargeFirst(nums, target, 0, len(nums)-1)
}
func DivideSelectLargeFirst(nums []int, target, start, end int) int {
if start > end {
return -1
}
middle := (start + end) / 2
if target <= nums[middle] {
if middle == 0 || nums[middle-1] < target {
return middle
} else {
return DivideSelectLargeFirst(nums, target, 0, middle-1)
}
} else {
return DivideSelectLargeFirst(nums, target, middle+1, end)
}
}
//二分法查找的变形版本:在给定序列中查找最后一个小于等于给定值的元素
func Divide2SelectSmallLast(nums []int, target int) int {
return DivideSelectSmallLast(nums, target, 0, len(nums)-1)
}
func DivideSelectSmallLast(nums []int, target, start, end int) int {
if start > end {
return -1
}
middle := (start + end) / 2
if target < nums[middle] {
return DivideSelectSmallLast(nums, target, 0, middle-1)
} else {
if middle == len(nums)-1 || nums[middle+1] > target {
return middle
} else {
return DivideSelectSmallLast(nums, target, middle+1, end)
}
}
}
参考来源:https://xueyuanjun.com/books/data-structure-and-algorithms