1、思想
对于一个升序数组,给定一个有序(非降序)数组A,求任意一个i使得A[i]等于target,不存在则返回-1
2、算法示例
3、算法实现
(1)非递归算法
public static int binarySearch(int[] value,int key){
int begin=0,end=value.length-1;
while(begin<=end){
int mid=(begin+end)/2;
if(value[mid]==key)
return mid;
if(value[mid]>key)
end=mid-1;
else
begin=mid+1;
}
return -1;
}
(2)递归算法
public static int binarySearchRecurrence(int[] value,int begin,int end,int key){
if(begin <= end){
int mid = (begin+end)/2;
if(value[mid] == key){
return mid;
} else if(value[mid] > key){
return binarySearchRecurrence(value, begin, mid-1, key);
} else{
return binarySearchRecurrence(value, mid+1 , end, key);
}
}
return -1;
}
(3)对于一个升序数组,给定一个有序(非降序)数组A,求最小的i使得A[i]等于target,不存在则返回-1
public static int binarySearchmix(int[] value,int key){
int begin=0,end=value.length-1;
while(begin<end){
//如果最后剩下 begin,end(begin),并且两个值相同
int mid=begin+(end-begin)/2;//mid为中间位置偏左
if(value[mid]<key)
begin=mid+1;
else//value[mid]>=key
end=mid;
}
//begin=end
if(value[end]==key)
return end;
else
return -1;
}
(4)给定一个有序(非降序)数组A,可含有重复元素,求最大的i使得A[i]等于target,不存在则返回-1
public static int binarySearchmax(int[] value,int key){
int begin=0,end=value.length-1;
while(begin<end){
//如果最后剩下 begin,end(begin),并且两个值相同。若mid偏左 怎么会出现死循环
int mid=end-(end-begin)/2;//mid为中间位置偏右
if(value[mid]<=key)
begin=mid;
else
end=mid-1;
}
if(value[end]==key)
return end;
else
return -1;
}
(5)统计出现的次数
public static int binarySearchCount(int[] value, int key){
// 找出key在value中最左边的位置
int left = binarySearchmix(value, key);
if(left == -1){
return -1;
}
// 找出key在value中最右边出现的位置
int right = binarySearchmax(value, key);
return right-left;
}
(6)循环升序数组,无重复元素
一个有序(升序)数组,没有重复元素,在某一个位置发生了旋转后,即递增数组右移。求target在变化后的数组中出现的位置,不存在则返回-1)。比如4、5、6、7、1、2、3
public static int binarySearchcircu(int[] value,int key){
int begin=0,end=value.length-1;
while(begin<=end){
int mid=begin+(end-begin)/2;
if(value[mid]==key)
return mid;
if(value[mid]>value[begin]){
//begin~mid 升序
if(key<value[mid]&&key>=value[begin])
end=mid-1;
else
begin=mid+1;
}
else{
//mid~end 升序
if(key>value[mid]&&key<value[end])
begin=mid+1;
else
end=mid-1;
}
}
return -1;
}
(7)调用结果
/**
* 二分查找
* @author zzj
*
*/
public class BinarySearch {
public static void main(String[] args){
int[] table={1,4,5,5,5,5,15,16,18,20};
int key =5;
System.out.println("原始数组为:"+Arrays.toString(table));
System.out.println("查找的key为:"+key);
// 1、非递归
int index1=binarySearch(table,key);
System.out.println("非递归找到一个退出,"+key+"下标为:"+index1);
// 2、递归
int index2 = binarySearchRecurrence(table, 0, 9, key);
System.out.println("递归找到一个退出,"+key+"下标为:"+index2);
// 3、出现位置最小的下标
int indexMix=binarySearchmix(table,key);
System.out.println(key+"下标最小的值:"+indexMix);
// 4、出现位置最大的下标
int indexMax=binarySearchmax(table,key);
System.out.println(key+"小标最大的值:"+indexMax);
// 5、统计出现的次数
int count= binarySearchCount(table, key);
System.out.println(key+"出现的次数:"+count);
// 6、循环升序数组
int[] circuTable = {4,5,6,7,1,2,3};
int circuKey = 1;
System.out.println("原始数组为:"+Arrays.toString(circuTable));
System.out.println("查找的key为:"+circuKey);
int indexCircu = binarySearchcircu(circuTable, 1);
System.out.println("循环升序数据,"+key+"下标为"+indexCircu);
}
}
调用结果:
原始数组为:[1, 4, 5, 5, 5, 5, 15, 16, 18, 20]
查找的key为:5
非递归找到一个退出,5下标为:4
递归找到一个退出,5下标为:4
5下标最小的值:2
5小标最大的值:5
5出现的次数:3
原始数组为:[4, 5, 6, 7, 1, 2, 3]
查找的key为:1
循环升序数据,5下标为4
4、算法分析
时间复杂度:O(logn)