网上很多关于斐波那契查找算法的解释都是有问题的,B站上韩顺平老师的讲解也有一定问题,在此提出我的看法和解决方案!
fibonacci[k]=fibonacci[k-1] + fibonacci[k-2]
==> (fibonacci[k]-1) = (fibonacci[k-1]-1) + 1 + (fibonacci[k-2]-1)
给你一个数组,
第一,找出第一个使得数组长度<=(fibonacci[k]-1)的k
第二,将数组“扩容”至fibonacci[k]-1,空的用数组的最后一个值填充,本质上是new一个数组,java不存在数组扩容
第三,计算斐波那契点,mid=left+fibonacci[k-1]-1
为什么是这个?
参考上面的公式,及下图
具体代码放下面,自己沾去IDE看,有疑问欢迎来喷554018182
常见错误:扩容不按公式来,一定要-1
package com.atguigu._09search;
import java.util.Arrays;
public class _04FibonacciSearch {
private static int maxSize = 10;
public static void main(String[] args) {
int[] arr = {3, 7, 12, 45, 132, 346};
int targetValue = 132;
int targetIndex = fibonacciSearch(arr, targetValue);
}
/**
* 斐波那契查找:重点是arr"扩容“至fibonacci[k]-1,每次循环操作的数组范围长度都为fibonacci[k]-1,往左k=k-1,往右k=k-2
* 因为:
* fibonacci[k]=fibonacci[k-1] + fibonacci[k-2]
* ==> (fibonacci[k]-1) = (fibonacci[k-1]-1) + 1 + (fibonacci[k-2]-1)
* 显而易见,需要保证每次的递归或循环操作的范围大小是一个斐波那契值-1,
* 中间的1就是mid索引指向的位置,我称之为斐波那契点
* @param arr
* @param targetValue
* @return
*/
private static int fibonacciSearch(int[] arr, int targetValue) {
//获取数组长度
int length = arr.length;
//获取斐波那契数组
int[] fibonacci = fibonacci(maxSize);
//定义指向斐波那契数组的索引
int k = 0;
//找出第一个使得length<=fibonacci[k]-1的k
while (length > (fibonacci[k] - 1)) {
k++;
}
//将原数组“扩容”至fibonacci[k]-1的长度,填充值为arr[length-1]
int[] temp = Arrays.copyOf(arr, fibonacci[k] - 1);
for (int i = length; i < fibonacci[k] - 1; i++) {
arr[i] = arr[length - 1];
}
//查找temp数组
int left = 0;//初始值
int right = temp.length - 1;//初始值
int mid = 0;
//循环查找
while (left <= right) {
//斐波那契点
mid = left + fibonacci[k - 1] - 1;
if (targetValue > temp[mid]) {
//目标值大于斐波那契点的值,往右查找,left置成斐波那契点右边一点,范围大小变为fibonacci[k-2]-1,需置k=k-2
left = mid + 1;
k -= 2;
} else if (targetValue < temp[mid]) {
//目标值小于斐波那契的值,往左查找,right置成斐波那契点左边一点,范围大小变为fibonacci[k-1]-1,需置k=k-1
right = mid - 1;
k -= 1;
} else {
//找到,若mid大于了length-1,则说明索引位于length-1,否则就是mid
if (mid >= length) {
return length - 1;
} else {
return mid;
}
}
}
return -1;
}
private static int[] fibonacci(int maxSize) {
int[] fibonacci = new int[maxSize];
fibonacci[0] = 1;
fibonacci[1] = 1;
for (int i = 2; i < maxSize; i++) {
fibonacci[i] = fibonacci[i - 1] + fibonacci[i - 2];
}
return fibonacci;
}
}