斐波那契查找原理
斐波那契(黄金分割法)原理:
斐波那契查找原理与前两种相似,仅仅改变了中间节点(mid)的位置,mid不再是中间或插值得到,而是位于黄金分割点附近,即mid=low+F(k-1)-1(F代表斐波那契数列)
我的理解
就是在数组中找黄金分割点的位置,并且要根据斐波那契数列{1,1,2,3,5,8,13,21...}才能找到黄金分割点,比如数组有6个数据,6不在斐波那契数列中,就找不到黄金分割点,必须就要添加到8个数据才能找到,而8个数据可分为5+3个数据,黄金分割点的位置就在第5个位置,同理,有5个数据的数组的黄金分割点在第3个位置。
这种算法我认为有两个难点:
- 理解斐波那契并不太容易,需要理解黄金分割点的意义并且理解怎么根据斐波那契数列进行寻找黄金分割点
- 理解完后,写代码也并不简单,不能眼高手低,代码逻辑需要非常缜密
代码实现
public static int fibSearch(int[] arr, int key) {
int low = 0;
int high = arr.length - 1;
int k = 0; //表示斐波那契分割数值的下标
int mid = 0; //存放mid值
int f[] = fib(); //获取到斐波那契数列
//根据数组长度,找到最开始斐波那契数列的小标
while (arr.length > f[k]) {
k++;
}
//因为 f[k] 值 可能大于 a 的 长度,因此我们需要使用Arrays类,构造一个新的数组,并指向temp[]
//不足的部分会使用0填充
int[] temp = Arrays.copyOf(arr, f[k]);
//实际上需求使用a数组最后的数填充 temp
//举例:
//temp = {1,8, 10, 89, 1000, 1234, 0, 0} => {1,8, 10, 89, 1000, 1234, 1234, 1234,}
for (int i = high + 1; i < temp.length; i++) {
temp[i] = arr[high];
}
// 使用while来循环处理,找到我们的数 key
while (low <= high) { // 只要这个条件满足,就可以找
mid = low + f[k - 1] - 1;
if (key < temp[mid]) { //我们应该继续向数组的前面(左边)查找
high = mid - 1;
//因为要找的值在左边,比如有8个数据,此时在我们代码中f[k]=8
//8可分为5+3,说明我们要在5个数据中继续找黄金分割点,在斐波那契数列中,8在5的前一位,所以k要减1
k -= 1;
} else if (key > temp[mid]) { // 我们应该继续向数组的后面(右边)查找
low = mid + 1;
//因为要找的值在右边,比如有8个数据,此时在我们代码中f[k]=8
//8可分为5+3,说明我们要在3个数据中继续找黄金分割点,在斐波那契数列中,8在3的前两位,所以k要减2
k -= 2;
} else { //找到
//需要确定,返回的是哪个下标,总不能返回的是自己添加的数据的下标吧
if (mid <= high) {
return mid;
} else {
return high;
}
}
}
return -1;
}