如何写对二分查找,要关注哪些细节?

很多人都玩过猜数字游戏。在1-100中选择1个数字,让你猜出是什么数字。猜错了会告诉你大了还是小了。 猜数字的这个过程就和二分查找的思想很相似,只不过二分查找每次都猜中间的数字。

二分查找过程:

  1. 获取中间位置
  2. 根据中间位置的值和目标值比较,相等就找到了。
  3. 不管的大了还是小了,都会排除掉一半。更改区间的边界,缩小查找范围。
  4. 使用剩下的一半重复这个过程,直到找到目标值。

二分查找的思想和实现都是比较简单的,大多数人理解和写出二分查找都是很容易的。但是要写对还是有一些细节需要注意的。

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
    }
};

注意点

  1. 数组的索引值是从0开始的,所以最右边的位置等于数组大小减1.
  2. 这里是"<=", 如果是"<“是有问题的,因为left和right相邻,取mid时,由于取整操作,mid只能取到left。+1后会终止循环。如果写成”<",在循环外需要再做处理。
  3. 此处很多人都会写成mid = (left + right) / 2; 这样在数字比较大的情况会存在溢出的可能。所以要写成left + (right - left) / 2 可以防止溢出问题。对应除以2的操作,使用位移效率会比较高。
  4. 不相等时的,要排除mid。所以要有+1,-1的操作。 只要注意排除范围的方向即可。
  5. 循环中没有找到,返回无效值。此处写为-1,不一定都是哦。
©️2020 CSDN 皮肤主题: 数字20 设计师:CSDN官方博客 返回首页