很多人都玩过猜数字游戏。在1-100中选择1个数字,让你猜出是什么数字。猜错了会告诉你大了还是小了。 猜数字的这个过程就和二分查找的思想很相似,只不过二分查找每次都猜中间的数字。
二分查找过程:
- 获取中间位置
- 根据中间位置的值和目标值比较,相等就找到了。
- 不管的大了还是小了,都会排除掉一半。更改区间的边界,缩小查找范围。
- 使用剩下的一半重复这个过程,直到找到目标值。
二分查找的思想和实现都是比较简单的,大多数人理解和写出二分查找都是很容易的。但是要写对还是有一些细节需要注意的。
class Solution {
public:
int search(vector<int>& nums, int target) {
int left = 0;
int right = nums.size() - 1; // 注意1
while (left <= right) { // 注意2
int mid = left + ((right - left) >> 1); // 注意3
if (nums[mid] > target) {
right = mid - 1; // 注意4
} else if (nums[mid] < target) {
left = mid + 1; // 注意4
} else {
return mid;
}
}
return -1; // 注意5
}
};
注意点
- 数组的索引值是从0开始的,所以最右边的位置等于数组大小减1.
- 这里是"<=", 如果是"<“是有问题的,因为left和right相邻,取mid时,由于取整操作,mid只能取到left。+1后会终止循环。如果写成”<",在循环外需要再做处理。
- 此处很多人都会写成mid = (left + right) / 2; 这样在数字比较大的情况会存在溢出的可能。所以要写成left + (right - left) / 2 可以防止溢出问题。对应除以2的操作,使用位移效率会比较高。
- 不相等时的,要排除mid。所以要有+1,-1的操作。 只要注意排除范围的方向即可。
- 循环中没有找到,返回无效值。此处写为-1,不一定都是哦。