二分查找
...大约 2 分钟
704.二分查找
题目描述:给定一个 n
个元素有序的(升序)整型数组 nums
和一个目标值 target
,写一个函数搜索 nums
中的 target
,如果目标值存在返回下标,否则返回 -1
。
示例 1:
输入: nums = [-1,0,3,5,9,12], target = 9
输出: 4
解释: 9 出现在 nums 中并且下标为 4
示例 2:
输入: nums = [-1,0,3,5,9,12], target = 2
输出: -1
解释: 2 不存在 nums 中因此返回 -1
提示:
- 你可以假设
nums
中的所有元素是不重复的。 n
将在[1, 10000]
之间。nums
的每个元素都将在[-9999, 9999]
之间。
解题思路
本题描述说明:有序数组、无重复元素,这是使用二分查找的关键。
二分查找的思路并不难,难点在于它涉及到一些边界问题,比如到底是 left <= right
?还是left < right
?;是right = mid - 1
?还是right = mid
?
这里分享给大家一个小技巧
我们首先看要给出数组的边界,是[left,right]
还是[left,right)
,我们写循环条件是要合法的,当我们考虑left <= right
的时候,要看他满不满足条件,就比如[1,1]
,是合法的。而当给出的数组边界[left,right)
时,[1,1)
是不合法的,所以循环条件就得是left < right
;而是选择right = mid - 1
?还是right = mid
?也是要看边界条件的。当我们规定right
的值时,要考虑边界值是否被查找过,如果被查找过,下次循环就不用带上了,具体详情我们看代码!
func BinarySearch(s []int, target int) int {
left := 0
right := len(s) - 1
for left <= right {//这里给出的数据是[]int,left <= right是合法的
mid := left + (right - left) / 2
if s[mid] < target {
left = mid + 1
} else if s[mid] > target {
right = mid - 1 //当s[mid] > target时,因为[left,mid],s[mid]已经被查过了,所以下一次循环是不需要进行比较mid
} else {
return mid
}
}
return -1
}
总结
在解题之前,一定要申清题目给的条件,遇到不确定的地方,可以考虑极限情况。本题的循环条件以及初始条件都可以根据所查找的数组边界来解决。本题中mid:=left + (right - left) / 2
其实和mid := (left + right) / 2
效果是一样的,主要是有效防止了因为 left
和 right
太大,导致直接相加数值溢出的情况。