【golang必备算法】二分查找

569 阅读1分钟

二分查找

基本二分查找

在无重复的有序数组中查找目标数下标

 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…

\