二分查找
https://labuladong.gitee.io/algo/2/21/61/
基本二分查找:查找一个元素
https://leetcode-cn.com/problems/binary-search/
| func search(nums []int, target int) int { left, right := 0, len(nums) - 1
for left <= right { mid := left + (right - left) / 2 if nums[mid] == target { return mid } else if nums[mid] < target { left = mid + 1 } else { right = mid - 1 } } return -1 }
|
查找左右侧边界
- 统一所有的二分查找为查找两头闭区间,左右指针初始化为
0, len(nums) - 1
- while 循环条件全都是
left <= right
- 所有的区间更新都是
left = mid + 1
或 right = mid - 1
- 找到目标后不马上返回,而是收缩另一侧的边界(想要得到哪一侧,就收缩另一侧)
- while 循环结束后返回想要的边界指针,需要判断有没有溢出、以及目标有没有找到。
实战:在排序数组中查找元素的第一个和最后一个位置
https://leetcode-cn.com/problems/find-first-and-last-position-of-element-in-sorted-array/
分别以寻找左侧和右侧边界作为例子。注意,两段代码只有在有注释的地方不同,其余都是一样的。
这寻找左侧边界:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| func searchRange(nums []int, target int) []int { left, right := 0, len(nums) - 1
for left <= right { mid := left + (right - left) / 2 if nums[mid] < target { left = mid + 1 } else if nums[mid] > target { right = mid - 1 } else { right = mid - 1 } }
if left >= len(nums) || nums[left] != target { return []int{-1, -1} }
for i := left; i < len(nums); i++ { if nums[i] != target { break } right = i }
return []int{left, right} }
|
如果改成寻找右边界:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| func searchRange(nums []int, target int) []int { left, right := 0, len(nums) - 1
for left <= right { mid := left + (right - left) / 2 if nums[mid] < target { left = mid + 1 } else if nums[mid] > target { right = mid - 1 } else { left = mid + 1 } } if right < 0 || nums[right] != target { return []int{-1, -1} }
for i := right; i >= 0; i-- { if nums[i] != target { break } left = i }
return []int{left, right} }
|