算法: 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. 二分查找的主要内容,如果未能解决你的问题,请参考以下文章