二分搜索算法

二分搜索算法

二分搜索

对于一组有顺序的数据,不采用常见的遍历方式找到需要的数据,而是利用其规律,比中间数据小的一定在中间数据左边,比中间数据大的一定在中间数据右边,每次排除一般的数据,从而提高搜索算法的时间复杂度。

模板

这里确保目标数据一定存在于数组当中

public int binarySearch(int[] nums, int target) {
        int left = 0, right = nums.length - 1;// 确定取值范围
        while (left < right) {
            int mid = left + (right - left) / 2;// 确定中间值
            int num = nums[mid];
            if (num > target) {// 缩小区间范围
                right = mid - 1;
            } else if (num < target) {
                left = mid + 1;
            } else {
                return mid;
            }
        }
        return left;
    }
注意点
1、取值范围确定

这道题由于数据一定存在于数组当中,所以其下标的取值一定是0~数组长度-1,所以我们将left = 0,right = nums.length - 1,其他的题目也是相同的道理。

2、mid中间值确定

有人说mid中间值可以直接使用**(left + right) / 2得到,确实是这样,但是当left和right的值特别大的时候,可能导致两者相加超出int类型或者其他数值类型的取值范围,所以建议还是采用left + (right - left) / 2这种方式获取mid中间值较为安全。但是并不一定每一获取中间值都是left + (right - left) / 2**,还有可能是left + (right - left + 1) / 2这种情况,这需要在第三步完成之后才能判断出来,用于解决跳不出循环的问题。

3、如何缩小区间范围

对于这道题如果mid取值比目标值target小,那么一定在其右边left = mid + 1,反之则是一定在其左边right = mid - 1,这种情况下并不存在跳不出循环的问题,mid中间值确定的两种方式都可。但是如果是这道题35. 搜索插入位置 - 力扣(LeetCode)就需要注意一下,由于目标值可能不存在,如果mid取值比目标值target小,那么一定在其右边left = mid + 1,但是如果比目标值大,那么就可能是mid位置,也有可能是在mid左边,于是right = mid,此时mid中间值的计算方式为left + (right - left) / 2,那是因为假设此时left = 0,right = 1,nums[left] = 0,nums[right] = 2,target = 1,这时mid = 0 + (1 - 0) / 2 = 0,这时的结果就为1。但是如果mid = 0 + (1 - 0 + 1) / 2 = 1,那么则会一直重复right = 1这个操作,从而导致循环无法结束。所以通俗的来讲,mid中间值的确定在于left = mid还是right = mid,如果是left = mid,那么mid = left + (right - left + 1) / 2,如果right = mid,那么mid = left + (right - left) / 2

你可能感兴趣的:(算法,算法)