数据结构–查找
二分查找
- 方法一:轴点取中点,逐步递归。算法时间复杂度O(log[n])。主要思路如下图:
<pre>
public class LinearRecur {
public static void main(String[] args) {
int[] b = {2,6,6,9,10,10};
int low = 0;
int high = b.length;
int index = 0;
index = binarySearch(b, low,high, 2);
System.out.print(index);
}
public static int binarySearch(int[] array, int low, int high, int num) {
if(high - low == 1) {
if (array[low] == num) {
return low;
}
return -1;
}
int middle = 0;
int index = 0;
middle = (low + high) / 2;
if (num == array[middle]) {
return middle;
}
if (num < array[middle]) {
index = binarySearch(array, low, middle, num);
return index;
}
if (array[middle] < num) {
index = binarySearch(array, middle+1, high, num);
return index;
}
return -1; //不会执行
}
}
</pre>
对于该算法,我们可以计算出迭代到底部所耗费的时间,计算结果如下图所示。从图中可以看出左边递归和右边递归所耗费的步数是不一样的,那我我们是否可以找到一种算法让左边迭代步数和右边一致能,这样能够减少平均迭代时间。如下图所示的斐波那契搜索每次迭代不再是选择中点进行分割。进而,对于这个问题我们可以找到最优的黄金分割点实现最低的时间复杂度。
2. 方法二:二分查找的改进策略。为了解决左右两边搜索不平衡问题,我们需要做一些操作,即让左右两边的判断次数一致,即:
<pre>
public class LinearRecur {
public static void main(String[] args) {
int[] b = {2,6,6,9,10,11};
int low = 0;
int high = b.length;
int index = 0;
index = binarySearch(b, low, high, 2);
System.out.print(index);
}
public static int binarySearch(int[] array, int low, int high, int num) {
if (num == array[low]) {
return low;
}else if(high - low == 1) {
return -1;
}
int middle = 0;
int index = 0;
middle = (low + high) / 2;
if (num < array[middle]) {
index = binarySearch(array, low, middle, num);
return index;
}else {
index = binarySearch(array, middle, high, num);
return index;
}
}
}
</pre>
3.方法三:二分查找的改进策略。对于一个二分查找算法,我们一般存在一些语义约定。对于一个有序数组,我们总希望查找后的返回的index能够为我们接下来的一些操作带来便利。例如,我们希望在新的数组中插入一个数而不改变原数组的有序性,那么我们对在原数组中查找返回的结果总是存在一定语义要求,为了满足我们的语义要求,我们可以通过下述算法来实现。总体的思路如下:
<pre>
public class LinearRecur {
public static void main(String[] args) {
int[] b = {2,6,6,9,10,11};
int low = 0;
int high = b.length;
int index = 0;
index = binarySearch(b, low, high, 10);
System.out.print(index);
}
public static int binarySearch(int[] b, int low, int high, int num) {
int index = 0;
while(low < high) {
int middle = 0;
middle = (low + high) / 2;
if (num < b[middle]) {
high = middle;
}else {
low = middle + 1;
}
}
return --low;
}
}
iddle]) {
high = middle;
}else {
low = middle + 1;
}
}
return --low;
}
}
</pre>