Java算法篇之二分查找算法

1 Java算法篇之二分查找算法

1.1 什么是二分查找算法?

  • 算法定义

二分查找算法又叫折半查找算法, 是一种基于比较目标值和数组中间元素的教科书式算

  • 使用条件

待查找的数组必须是有顺序的

  • 复杂度

空间复杂度:O(1)

  • 时间复杂度最好情况:O(1)
  • 时间复杂度最坏情况:O(LogN) 一般默认指这种。
    注意:
    可能也听过下面这种说法:
    在这里插入图片描述
    它们两个其实是等价的,log2n 的意思是以2为底数,然后n.
  • 算法规则
  • 如果目标值等于中间元素,则找到目标值。
  • 如果目标值较小,继续在左侧搜索。
  • 如果目标值较大,则继续在右侧搜索。
    在这里插入图片描述

1.2 二分查找算法分析

LeetCode最佳算法解析,请移步二分查找细节详解,顺便赋诗一首

  • 初始化指针 left = 0, right = n - 1。
  • 当 left <= right:
  • 比较中间元素 nums[pivot] 和目标值 target 。
    • 如果 target = nums[pivot],返回 pivot。
    • 如果 target < nums[pivot],则在左侧继续搜索 right = pivot - 1。
    • 如果 target > nums[pivot],则在右侧继续搜索 left = pivot + 1。
      在这里插入图片描述

1.3 Solution

1.3.1 LeetCode 官方解法

LeetCode 官方二分法解法

class Solution {
  public int search(int[] nums, int target) {
    int pivot, left = 0, right = nums.length - 1;
    while (left <= right) {
      pivot = left + (right - left) / 2;
      if (nums[pivot] == target) return pivot;
      if (target < nums[pivot]) right = pivot - 1;
      else left = pivot + 1;
    }
    return -1;
  }
}

作者:LeetCode
链接:https://leetcode-cn.com/problems/binary-search/solution/er-fen-cha-zhao-by-leetcode/
来源:力扣(LeetCode) 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

1.3.2 最佳二分法查找Solution

给大家讲个笑话乐呵一下:

  • 有一天阿东到图书馆借了 N本书,出图书馆的时候,警报响了,于是保安把阿东拦下,要检查一下哪本书没有登记出借。阿东正准备把每一本书在报警器下过一下,以找出引发警报的书,但是保安露出不屑的眼神:你连二分查找都不会吗?于是保安把书分成两堆,让第一堆过一下报警器,报警器响;于是再把这堆书分成两堆……
  • 最终,检测了 logN 次之后,保安成功的找到了那本引起警报的书,露出了得意和嘲讽的笑容。于是阿东背着剩下的书走了。
  • 从此,图书馆丢了 N - 1 本书。

事故现场还原:

数组下标:0 1 2 3 4 
存储内容:1 2 2 2 3

比如说给你有序数组 nums = [1,2,2,2,3],target 为 2,上面算法返回的索引是 2,没错。但是如果我想得到 target 的左侧边界,即索引 1,或者我想得到 target 的右侧边界,即索引 3,这样的话此算法是无法处理的。

解决上述需求,完整算法如下:

保安用的基础二分法算法如下:

//和官方的Leetcode 算法一致
//基础二分查找算法
int binary_search(int[] nums, int target) {
    int left = 0, right = nums.length - 1; 
    while(left <= right) {
        int mid = left + (right - left) / 2;
        if (nums[mid] < target) {
            // 搜索区间变为 [mid+1, right]
            left = mid + 1;
        } else if (nums[mid] > target) {
            // 搜索区间变为 [left, mid-1]
            right = mid - 1; 
        } else if(nums[mid] == target) {
            // 直接返回
            return mid;
        }
    }
    // 直接返回
    return -1;
}

左侧边界二分法算法如下:

//左侧边界查找算法
int left_bound(int[] nums, int target) {
    int left = 0, right = nums.length - 1;
    while (left <= right) {
        int mid = left + (right - left) / 2;
        if (nums[mid] < target) {
            left = mid + 1;
        } else if (nums[mid] > target) {
            right = mid - 1;
        } else if (nums[mid] == target) {
            // 别返回,收缩左侧边界
            right = mid - 1;
        }
    }
    // 最后要检查 left 越界的情况
    if (left >= nums.length || nums[left] != target){
        return -1;
    }
    return left;
}

右侧边界二分法算法如下:

//右侧边界查询算法
int right_bound(int[] nums, int target) {
    int left = 0, right = nums.length - 1;
    while (left <= right) {
        int mid = left + (right - left) / 2;
        if (nums[mid] < target) {
            left = mid + 1;
        } else if (nums[mid] > target) {
            right = mid - 1;
        } else if (nums[mid] == target) {
            // 别返回,收缩右侧边界
            left = mid + 1;
        }
    }
    // 最后要检查 right 越界的情况
    if (right < 0 || nums[right] != target){
        return -1;
    }
    return right;
}

作者:labuladong
链接:https://leetcode-cn.com/problems/binary-search/solution/er-fen-cha-zhao-xiang-jie-by-labuladong/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

更多学习资源:https://github.com/labuladong/fucking-algorithm

本篇完~

发布了194 篇原创文章 · 获赞 262 · 访问量 48万+

猜你喜欢

转载自blog.csdn.net/hadues/article/details/105296710