二分查找
基本二分查找
在无重复的有序数组中查找目标数下标
func search(nums []int,target int)int{
low,high := 0,len(nums)-1
mid := 0
for low <= high{
mid = low + (high-low)/2
if nums[mid] == target{
return mid
}else if nums[mid] > target{
high = mid - 1
}else if nums[mid] > target{
low = mid + 1
}
}
return -1
}
为什么 while 循环的条件中是 <=,而不是 < ?
因为初始化 high 的赋值是 len(nums)-1,即最后一个元素的索引,而不是 len(nums)。
这二者可能出现在不同功能的二分查找中,区别是:前者相当于两端都闭区间 [low, high],后者相当于左闭右开区间 [low, high),因为索引大小为 len(nums) 是越界的。
我们这个算法中使用的是前者 [low, high] 两端都闭的区间。这个区间其实就是每次进行搜索的区间。
什么时候应该停止搜索呢?当然,找到了目标值的时候可以终止:
if(nums[mid] == target)
return mid;
但如果没找到,就需要 for 循环终止,然后返回 -1。那 for 循环什么时候应该终止?搜索区间为空的时候应该终止,意味着你没得找了,就等于没找到嘛。
while(low <= high) 的终止条件是 low == high + 1,写成区间的形式就是 [low, high],或者带个具体的数字进去 [3, 2],可见这时候区间为空,因为没有数字既大于等于 3 又小于等于 2 的吧。所以这时候 for 循环终止是正确的,直接返回 -1 即可。
寻找左侧边界的二分查找
在有重复元素的排序数组中找元素的第一个的下标
func search(nums []int,target int)int{
low,high := 0,len(nums)-1
for low <= high{
mid := low +(high-low)/2
if nums[mid] == target{
high = mid - 1
}else if nums[mid] > target{
high = mid - 1
}else{
low = mid + 1
}
}
//因为循环跳出条件为low = high + 1,当target比所有元素都大的话,此时high就是最后一个元素,low会越界,所以要判断一下
//当target比所有元素都小的话,此时low不会越界,但要判断一下nums[low] 和 target 相不相等,如nums数组为[1],不判断的话会返回0
if low >= len(nums) || nums[low] != target{
return -1
}
//因为不管怎么样high一定是 mid-1
//而循环跳出条件为low = high + 1,所以返回low
return low
}
寻找右侧边界的二分查找
在有重复元素的排序数组中找元素的最后一个的下标
func search(nums []int,target int)int{
low,high := 0,len(nums)-1
for low <= high{
mid := low +(high-low)/2
if nums[mid] == target{
low = mid + 1
}else if nums[mid] > target{
high = mid - 1
}else{
low = mid + 1
}
}
//判断是否越界
if low >= len(nums) || nums[high] != target{
return -1
}
//因为不管怎么样low一定是 mid+1
//而循环跳出条件为low = high + 1,也就是high = low - 1,所以返回high
return high
}
参考: labuladong.gitee.io/algo/2/18/2…
\