二分查找

114 阅读1分钟

二分查找(binary search),也称折半搜索(half-interval search)、对数搜索(logarithmic search),是一种在有序数组中查找某一特定元素的搜索算法。

搜索过程从数组的中间元素开始,如果中间元素正好是要查找的元素,则搜索过程结束;如果某一特定元素大于或者小于中间元素,则在数组大于或小于中间元素的那一半中查找,而且跟开始一样从中间元素开始比较。如果在某一步骤数组为空,则代表找不到。这种搜索算法每一次比较都使搜索范围缩小一半。

场景1:返回第一次匹配中的目标值,GO代码实现如下:

//nums是有序数组
func binarySearch(nums []int, target int) int {
   left, right := 0, len(nums)-1
   for left <= right {
      mid := (left + right) / 2
      if nums[mid] == target {
         return mid
      } else if nums[mid] > target {
         right = mid - 1
      } else {
         left = mid + 1
      }
   }
   return -1
}

时间复杂度:O(\log n)O(logn),其中 nn 是数组的长度。

场景2:数组有重复元素的情况下,返回目标值在数组中最小索引位置,GO代码实现如下:

func binarySearchLeftBound(nums []int, target int) int {
   left, right := 0, len(nums)-1
   for left <= right {
      mid := (left + right) / 2
      if nums[mid] > target {
         right = mid - 1
      } else if nums[mid] < target {
         left = mid + 1
      } else {
         right = mid - 1
      }
   }
   //没有匹配值
   if left == len(nums) || nums[left] != target {
      return -1
   }
   return left
}

场景3:数组有重复元素的情况下,返回目标值在数组中最大索引位置,GO代码实现如下:

func binarySearchRightBound(nums []int, target int) int {
   left, right := 0, len(nums)-1
   for left <= right {
      mid := (left + right) / 2
      if nums[mid] > target {
         right = mid - 1
      } else if nums[mid] < target {
         left = mid + 1
      } else {
         left = mid + 1
      }
   }
   if right<0 || nums[right] != target {
      return -1
   }

   return right
}