斐波那契查找
斐波那契查找算法
核心思想就是利用斐波那契公式来表示数组,将数组分割,通过比较分割点的大小
向左或者向右继续利用斐波那契公式来表示分割子数组
public class FibonacciSearch {
public static int maxSize = 20;
public static void main(String[] args) {
int[] arr = {1, 8, 10, 89, 1000, 1234};
System.out.println("index="+fibSearch(arr,8));
}
//因为后面我们mid=low+F(k-1)-1,需要使用到斐波那契数列,因此我们需要先获取到斐波那契数列
public static int[] fib() {
int[] f = new int[maxSize];
f[0] = 1;
f[1] = 1;
for (int i = 2; i < maxSize; i++) {
f[i] = f[i - 1] + f[i - 2];
}
return f;
}
//编写斐波那契查找算法
public static int fibSearch(int[] arr, int key) {
int k = 0;
int low = 0;
int high = arr.length - 1;
int mid = 0;
int[] f = fib();
//寻找能够表示数组的斐波那契数对应的索引
//f[k]代表数组长度 f[k-1]、f[k-2]分别对应两个子数组的长度
while (f[k] - 1 < high) {
k++;
}
//如果原数组长度不满足能够能在该数组中找到斐波那契黄金分割点的长度k就扩展数组长度
//并在temp数组里面查找
int[] temp = Arrays.copyOf(arr, f[k]);
for (int i = high + 1; i < temp.length; i++) {
temp[i] = arr[high];
}
while (low <= high) {
mid = low + f[k - 1] - 1;
if (key < temp[mid]) {//应该继续向数组的前面查找(左边)
high = mid - 1;
//为什么是k--
//全部元素 = 前面元素 + 后面元素
//f[k] = f[k-1]+f[k-2]
//即k个元素可以分成f[k-1]个前面元素 + f[k-2]个后面元素
//那么向前查找就是在k-1个元素里进行划分,左下标不变,右下标=mid-1
//f[k-1] = f[k-2]+f[k-3] f[k-2]就是划分点
k--;
} else if (key > temp[mid]) {//应该继续向数组的后面查找(右边)
//为什么是k-=2
//因为向后查找是在f[k-2]个后面元素里面划分,左下标=mid+1
//f[k-2]个元素是由f[k-3]个前面元素和f[k-4]个后面元素组成的
low = mid + 1;
k -= 2;
} else {
//找到了
//向前查找mid始终是小于high的,所以不用管
//向后查找,因为刚开始k>high f[k-2]个元素中包含了我们扩展的部分 m=f[k-1]+f[k-3]-1 mid的值可能会大于high
//所以如果mid大于high,high后面补充的都是arr[high]的值,如果找到后面也就是arr[high]的值,就返回high的下标
if(mid<=high){
return mid;
}else{
return high;
}
}
}
return -1;
}
}