二分搜索难点分析

  • 能使用二分搜索的前提是数组已排序。
  • 二分查找的使用场景:(1)可转换为find the first/last position of...(2)时间复杂度至少为O(lgn)。
  • 递归和迭代的使用场景:能用迭代就用迭代,特别复杂时采用递归。
    Ref:https://algorithm.yuanbin.me/zh-hans/binary_search/binary_search.md

leetcode 374

We are playing the Guess Game. The game is as follows:
I pick a number from 1 to n. You have to guess which number I picked.

Every time you guess wrong, I'll tell you whether the number is higher or lower.

You call a pre-defined API guess(int num) which returns 3 possible results (-1, 1, or 0):
-1 : My number is lower
1 : My number is higher
0 : Congrats! You got it!

Example:
n = 10, I pick 6.
Return 6.
public int guessNumber(int n) {
        int start = 1;
        int end = n;
        int mid;
        int tmp;
        while(start < end){
            mid = start/2 + end/2;
            tmp = guess(mid);
            if ( tmp == 0) return mid;
            else if ( tmp == 1){
                start = mid + 1;
            } else{
                end = mid - 1;
            }
        }
        return start;

    }

在上述程序中
mid = start/2 + end/2;
这里之所以这样写是防止两数相加后溢出。
while(start < end)
循环判断不取等号可以防止死循环。
当涉及数组时,我们经常会发生数组越界的情况,这种时候我们可以采取补项的思路。

定义 lower bound 为在给定升序数组中大于等于目标值的最小索引,upper bound 则为小于等于目标值的最大索引.以lower bound为例:

public static int lowerBound(int[] nums, int target) {
        if (nums == null || nums.length == 0) return -1;
        int lb = -1, ub = nums.length;
        while (lb + 1 < ub) {
            int mid = lb + (ub - lb) / 2;
            if (nums[mid] < target) {
                lb = mid;
            } else {
                ub = mid;
            }
        }

        return lb + 1;
    }

这里我们采取,使lb,ub在数组边界的两端+1,而不是刚好等于数组边界。
int lb = -1, ub = nums.length;

如果遇到有问插入索引的位置时,可以分三种典型情况:
1.目标值在数组范围之内,最后返回值一定是 lb + 1
2.目标值比数组最小值还小,此时 lb 一直为 -1 , 故最后返回 lb + 1 也没错,也可以将 -1 理解为数组前一个更小的值
3.目标值大于等于数组最后一个值,由于循环退出条件为 lb + 1 == ub , 那么循环退出时一定有 lb = A.length - 1 , 应该返回 lb + 1

你可能感兴趣的:(二分搜索难点分析)