判断给定的整数是否存在。只能用加法和减法以及常数的额外内存空间。程序的运行时间在最坏情况下应该和logN成正比。
书中给予的提示:用斐波那契数代替2的幂(二分法)进行查找。用两个变量保存Fk和Fk-1并在[i, i+Fk]之间查找。在每一步中,使用减法计算Fk-2,检查i+Fk-2处的元素,并根据结果将搜索范围变为[i, i+Fk-2]或是[i+Fk-2, i+Fk-2+Fk-1]。
设给定数组a的长度为N,目标数字为key,斐波那契数组的头3个数字是0,1,2,最后一个数字tail不能大于N-1。如果a[tail]<=key,则在[tail, N-1]范围内遍历寻找;如果a[tail]>key,则根据斐波那契数列在[0, tail]范围内查找。
设有斐波那契数列0,1,2,…,Fk, head=0, tail=Fk.
1.将数列分为3个部分,[head, head+Fk-1-1],head+Fk-1, [head+Fk-1, tail] (Fk=Fk-2+Fk-1), mid = head+Fk-1.
2.若a[head+Fk-1]>key,则head=mid+1,Fk,Fk-1,Fk-2相应迁移两个单位。
3.若a[head+Fk-1]<key,则tail=mid,Fk,Fk-1,Fk-2相应迁移一个单位。
关键代码:
public class FibonacciBinarySearch {
public boolean search(int[] a, int key) {
Arrays.sort(a);
int N = a.length;
int[] fibonacci = new int[50];
fibonacci[0] = 0; fibonacci[1] = 1; fibonacci[2] = 2;
int i = 0;
for(i = 2; fibonacci[i] <= N - 1; i ++) {
fibonacci[i + 1] = fibonacci[i] + fibonacci[i - 1];
}
int index = i - 1;
int head = 0, tail = fibonacci[index];
if(a[tail] > key) {
while(head < tail - 1) {
int mid = head + fibonacci[index - 1] - 1;
if(a[mid] < key) {
head = mid + 1;
index = index - 2;
} else if (a[mid] > key) {
tail = mid;
index --;
} else
return true;
}
if(a[head] == key)
return true;
if(a[tail] == key)
return true;
} else {
for(int k = tail; k < N - 1; k ++) {
if(a[k] == key)
return true;
}
}
return false;
}
}