算法: 14. 二分查找

Posted 自在遨游

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了算法: 14. 二分查找相关的知识,希望对你有一定的参考价值。

https://www.lintcode.com/problem/first-position-of-target/description

  • 描述
    给定一个排序的整数数组(升序)和一个要查找的整数target,用O(logn)的时间查找到target第一次出现的下标(从0开始),如果target不存在于数组中,返回-1

  • 样例
    在数组 [1, 2, 3, 3, 4, 5, 10] 中二分查找3,返回2

  • 挑战

    如果数组中的整数个数超过了2^32,你的算法是否会出错?


思路

看似简单,但是边界处理也要仔细。也是很容易出错的。

代码

 1public int binarySearch(int[] nums, int target) {
2    if(nums==null || nums.length==0) {
3        return -1;
4    }
5    int start=0, end=nums.length;
6    while(start<end) {
7        int mid = (start+end)/2;
8        if(nums[mid]==target) {
9            end = mid;
10        } else if(nums[mid]>target) {
11            end = mid-1;
12        } else {
13            start = mid+1;
14        }
15    }
16    return nums[end]==target?end:-1;
17}

有一个地方可改进,int mid = (start+end)/2; 这一句中当start+end大于 Integer.MAX_VALUE 时会产生溢出,造成数组下标异常。可以改进为 int mid = start + (end-end)/2; 或者 int mid = (start+end)>>>1;

对于挑战提到的当数组大小超过2^32时,会不会溢出的问题。在计算mid时,按照上面的算法已经尽量避免了int类型溢出的情况,但是如果数组非常大,依然会产生溢出的情况,再第一步计算 start+(end-start)/2 时,end就已经溢出了。

在Java中,数组的大小本身就是int类型,系统实现的链表的大小也是int类型。如果数组非常大,在不考虑内存限制的情况下,可能需要进行分组,然后进行分组查询。例如将一个 2^32的分成 两个 2^31的。



以上是关于算法: 14. 二分查找的主要内容,如果未能解决你的问题,请参考以下文章

14Java常用类(StringBuffer)排序算法(冒泡排序选择排序插入排序快速排序)查找算法(二分查找)

[基础算法]二分查找Binary Search

#14 二分查找(Binary Search)

Linux内核(14) - 二分法与printk

二分查找算法

14. 二分查找