刚才看到五大常用算法之一的分治法,分治法有分而治之的思想,把规模不断的缩小,这样就会用到递归。二分查找也是分治法的一种实现。
在二分查找算法的两种实现方式中,就有一个是递归的实现方式,另一种就是循环的实现方式。
二分查找算法实现的前提:已排序的数组。
二分查找(折半查找)算法原理:将已排好序的数组,取出最小值的下标(即第一个值)和最大值的下标(即数组中的最后一个值)。根据这两个值得到数组的中间值的下标已经所对应的中间值,并根据这个中间值与需要查找的数进行判断大小。如果相等,就直接输出该值。如果中间值小于需要查找的数,让循环实现或者递归实现的最小值范围变为中间值+1,。如果中间值大于需要查找的数,让实现的最大值变为中间值-1。依次缩小范围,如果这个需要查找的元素在数组中就会输出那个值所对应的下标;如果这个值不在数组中,就会返回-1。
时间复杂度:最好的情况肯定是O(1)
平均时间复杂度:O(lgn)
推理过程: 查找第1次能找到,会定位1个位置,查到的概率是1/n;
查找第2次能找到,会定位2个位置,查到的概率是2/n;
查找第3次能找到,会定位4个位置,查到的概率是4/n;
......
查找第n次能找到,会定位2^m-1个位置,查到的概率是(2^m-1)/n;
由于有n个元素,最多会查m次,根据求和公式
以下是我借鉴别人的代码,但是也是自己手动敲上去,明白其中的原委。
为了图省事,测试和实现的内容都写在一个类里面了。
public class BinarySearch {
private int rCount = 0;
private int lCount = 0;
//计算递归的次数
public int showRecursionCount() {
return rCount;
}
//计算循环的次数
public int showLoopCount() {
return lCount;
}
/**
* 利用递归实现二分查找
* @param orderArray 已经排好序的数组
* @param left 数组最左边的值
* @param right 数组最右边的值
* @param findValue 查找的元素
* @return
*/
public int recursionBinarySearch(int[] orderArray, int left, int right, int findValue) {
rCount++;
if(left <= right) {
int middle = (left + right) / 2;
int middleValue = orderArray[middle];
if(findValue == middleValue) {
return middle;
} else if(findValue > middleValue) {
return recursionBinarySearch(orderArray, middle + 1, right, findValue);
} else {
return recursionBinarySearch(orderArray, left, middle - 1, findValue);
}
} else {
return -1; //需要查找的数不在数组范围内
}
}
/**
* 利用循环实现二分查找
* @param orderArray 已经排好序的数组
* @param findValue 查找的元素
* @return
*/
public int loopBinarySearch(int[] orderArray, int findValue) {
int start = 0;
int end = orderArray.length - 1;
while(start <= end) {
lCount++;
//中间值
int middle = start + (end - start) / 2;
int middleValue = orderArray[middle];
if(findValue == middleValue) {
return middle;
} else if(findValue < middleValue) {
end = middle - 1;
} else {
start = middle + 1;
}
}
return -1; //找不到的时候
}
public static void main(String[] args) {
int[] orderArray = {1,3,5,6,7,8,9,11,14,21,35};
int findValue = 9;
int length = orderArray.length;
BinarySearch binarySearch = new BinarySearch();
int index = binarySearch.recursionBinarySearch(orderArray, 0, length - 1, findValue);
int reTimes = binarySearch.showRecursionCount();
System.out.println("利用递归的二分查找,得到该值在数组中的位置" + index + ",循环次数为" + reTimes);
index = binarySearch.loopBinarySearch(orderArray, findValue);
int loopTimes = binarySearch.showLoopCount();
System.out.println("利用循环实现的二分查找,得到该值在数组中的位置" + index + ",循环次数为" + loopTimes);
}