力扣刷题——二分模版详细推导,不需要死记硬背Java

目录

步骤

额外注意

时间复杂度——O(logn)

空间复杂度——O(1)

1.严格有序数组查找==target的数字,没有返回-1

2.有序数组查找刚好>=target的数字,没有返回-1

3.有序数组查找刚好<=target的数字,没有返回-1

不需要死记硬背,灵活理解使用。

步骤

前提条件是数组满足二段性(有序性包涵在二段性内),前面一段满足某个性质,后面一段满足另一个性质。通常遇见的都是有序性。

  1. 注意判断一开始的边界条件, 比如n == 0.
  2. 定义的时候,只需要记住一种模版就行,就是l = 0,  r = n - 1, while(l < r), return l 
  3. mid 有两种情况,一种是(l + r) >> 1 或者是 (l + r + 1)>> 1。mid 是否+ 1主要看 l 是否有+1的操作, 如果l = mid, 那么mid = (l + r + 1) >> 1; 如果l = mid + 1, 那么mid = (l + r) >> 1
  4. l 是否+1 或者 r 是否需要 -1,其实道理是一样的。因为while循环中最后返回的时候一定有l == r, 而我们所需要的答案就是l或者r, 所以我们需要判断l 或者r 是否是我们可能的目标,如果可能是我们最终的答案,那么l不需要进行+1,r 不需要进行-1。
  5. 最终我们需要的结果,就是l 或者 r, 也有可能找不到,也就是-1

举个例子:假如我们的目标是找到有序数组中第一个<=target的数字。在if(nums[mid] <= target),分支中,我们来确定l = mid, 还是l = mid + 1.答案是l = mid .

因为此时的mid 是可能属于我们的目标的,因为if分支就是小于等于,所以根据上述第4点想法,此时l = mid.那么 mid 的更新就应该是mid = (l + r + 1) >>1, 保证不陷入死循环。

同理, 我们来判断另一个if分支if(nums[mid] > target)中,r = mid , 还是 r = mid - 1。答案是r = mid - 1.

因为在这个if分支中是大于,不是我们想找到的小于等于,所以此时mid 不是我们的目标,那么需要进行-1,也就是r = mid - 1.

其他的情况也是类似推导即可,只需要理解。

额外注意

mid的更新还可以是以下两种写法

int mid = l + (r - l ) / 2.这个主要是为了防止(l + r)越界。(或者直接用long 定义mid)

int mid = (l + r) / 2;移位的计算会比直接除法更快,所以通常用移位。

时间复杂度——O(logn)

空间复杂度——O(1)

1.严格有序数组查找==target的数字,没有返回-1

    // 找到等于target
    public int getIndex(Listlist, int target){
        int n = list.size();
        if(n == 0) return -1;
        int l = 0, r = n - 1;
        while(l < r){
            int mid = (l + r) >> 1;
            if(lis.get(mid) == target)
                return target;
            else if(list.get(mid) < target)
                l = mid + 1;
            else
                r = mid - 1;
        }
        if(l < n && list.get(l) == target) return list.get(l);
        else return -1;
    }

2.有序数组查找刚好>=target的数字,没有返回-1

    // 找到第一个大于等于target
    public int getIndex1(Listlist, int target){
        int n = list.size();
        if(n == 0) return -1;
        int l = 0, r = n - 1;
        while(l < r){
            int mid = (l + r) >> 1;
            if(list.get(mid) < target)
                l = mid + 1;
            else
                r = mid;
        }
        if(l < n && list.get(l) >= target) return list.get(l);
        else return -1;
    }

3.有序数组查找刚好<=target的数字,没有返回-1

// 找到小于等于target
    public int getIndex2(Listlist, int target){
        int n = list.size();
        if(n == 0) return -1;
        int l = 0, r = n - 1;
        while(l < r){
            int mid = (l + r + 1) >> 1;
            if(list.get(mid) <= target)
                l = mid;
            else
                r = mid - 1;
        }
        if(l < n && list.get(l) <= target) return list.get(l);
        else return -1;
    }

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