美文网首页
[Java]LeetCode. Binary Search 二

[Java]LeetCode. Binary Search 二

作者: 葵sunshine | 来源:发表于2019-03-11 23:24 被阅读0次

    特点:被搜索序列有序;可以随机访问

    二分查找一般由三个主要部分组成:

    1. 预处理 —— 如果集合未排序,则进行排序。
    2. 二分查找 —— 使用循环或递归在每次比较后将查找空间划分为两半。
    3. 后处理 —— 在剩余空间中确定可行的候选者。

    1. 时间复杂度

    二分搜索的时间复杂度正比于while的循环次数

    循环次数 剩余元素
    1 N/2
    2 N/2^2
    3 N/2^3
    k N/(2^k)

    易知,剩余元素 >=1,
    最差情况是在剩余一个元素的情况下找到目标值,则有 N/(2^k) = 1
    得到循环次数为k = log(2^N)
    时间复杂度可表示为O(N) = O(logN)

    2. 模版

    Template #1:
    int binarySearch(int[] nums, int target){
      if(nums == null || nums.length == 0)
        return -1;
    
      int left = 0, right = nums.length - 1;
      while(left <= right){
        // Prevent (left + right) overflow
        int mid = left + (right - left) / 2;
        if(nums[mid] == target){ return mid; }
        else if(nums[mid] < target) { left = mid + 1; }
        else { right = mid - 1; }
      }
    
      // End Condition: left > right
      return -1;
    }
    

    Exercise #1:求一个数的平方根

    返回类型为 int ,开方后的小数部分略去

    public int sqrt(int x) {
        if (x == 0)
            return 0;
        int left = 1, right = x;
        while (true) {
            int mid = left + (right - left)/2;
            if (mid > x/mid) {  //不能换为 mid * mid > x ,因为当 mid 过于大时,平方后会溢出
                right = mid - 1;
            } else {
                if (mid + 1 > x/(mid + 1))
                    return mid;
                left = mid + 1;
            }
        }
    }
    
    Exercise #2:猜数字大小

    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!
    
    public class Solution extends GuessGame {
        //My" means the number which is given for you to guess not the number you put into guess(int num).
        public int guessNumber(int n) {
            if(guess(n) == 0) return n;
            int left = 1, right = n;
            while(left <= right){
                int mid = left + (right - left)/2;
                if(guess(mid) == 0) return mid;
                else if(guess(mid) == -1) right = mid - 1;
                else left = mid + 1;
            }
            return -1;
        }
    }
    
    Exercise #3:搜索旋转排序数组

    0 1 2 \color{orange}{4 5 6 7}
    \color{orange}{1 2 4 5} 6 7 0
    \color{orange}{2 4 5 6} 7 0 1

    1. 因为 Binary Search 需要在获得中间数后,判断下一次是搜索左半段还是右半段,可以用 mid 值和 right 值比较:
      mid 值 < right 值 说明右半段;否则,左半段有序;
    2. 在有序的半段中判断目标值是否在此区域内,以确定要保留哪边。
    public int search(int[] nums, int target) {
            if(nums == null || nums.length == 0) return -1;
            int left = 0, right = nums.length - 1;
            while(left <= right){
                int mid = left + (right - left) / 2;
                if(nums[mid] == target) return mid;
                else if(nums[mid] < nums[right]){  //右半段有序
                    if(nums[mid] < target && nums[right] >= target) left = mid + 1;
                    else right = mid - 1;
                }else{
                    if(nums[mid] > target && nums[left] <= target) right = mid - 1;
                    else left = mid + 1;
                }
            }
            return -1;
        }
    


    Template #2:

    左闭右开区间:right = nums.length, right = mid

    int binarySearch(int[] nums, int target){
      if(nums == null || nums.length == 0)
        return -1;
    
      int left = 0, right = nums.length;
      while(left < right){
        // Prevent (left + right) overflow
        int mid = left + (right - left) / 2;
        if(nums[mid] == target){ return mid; }
        else if(nums[mid] < target) { left = mid + 1; }
        else { right = mid; }
      }
    
      // Post-processing:
      // End Condition: left == right
      if(left != nums.length && nums[left] == target) return left;
      return -1;
    }
    

    相关文章

      网友评论

          本文标题:[Java]LeetCode. Binary Search 二

          本文链接:https://www.haomeiwen.com/subject/rouipqtx.html