algorithm:斐波那契查找

import java.util.Arrays;

public class FibonacciSearch {
    public static void main(String[] args) {
        int[] arr = {1, 2, 4, 9, 19, 34};
        int index = fibSearch(arr, 1);
        if (index == -1) {
            System.out.println("该数未找到!");
        } else {
            System.out.println("该数在第" + index + "位。");
        }
    }

    /**
     * 由斐波那契数列 F(k) = F(k-1) + F(k-2) 的性质,得到 F(k)-1 = ( F(k-1)-1 ) + ( F(k-2)-1 ) + 1
     * 说明可以将长度为 F(k)-1 的数列,划分成长度分别为 F(k-1)-1 和 F(k-2)-1 的两段
     * 中间位置的下标 mid = start + F(k-1)-1
     * 当数组中元素的个数和斐波那契数列中元素的个数不相等时,采用“大于数组长度的最近一个斐波那契数值”
     * 比如当前数组长度为6,斐波那契数列中大于6的最近元素为8
     * 进行数值填充,将数组从6个元素填充到8个,采用第6个元素的值对不足的部分进行填充
     */
    public static int fibSearch(int[] arr,int value) {
        int start = 0;
        int end = arr.length - 1;
        int mid = 0;

        // 斐波那契分割点的下标
        int k = 0;

        // 获取斐波那契数列
        int[] f = fibonacci();

        // 从第一个斐波那契数开始,通过比较获取到大于数组长度的最近一个斐波那契数值
        // 比较的两个数都为下标,正常位置-1
        while (end > f[k] - 1) {
            k++;
        }

        // f[k]的值会大于arry的长度,构造一个f[k]数值长度的数组,不足的部分默认用0填充
        int[] temp = Arrays.copyOf(arr, f[k]);
        // 将不足的部分用arr数组最后的数填充
        for (int i = end + 1; i < temp.length; i++) {
            temp[i] = arr[end];
        }

        // 使用while循环,采用非递归的方式查找value
        while (start <= end && value >= arr[0] && value <= arr[arr.length - 1]) {
            mid = start + f[k - 1] - 1;
            if (value < temp[mid]) {
                end = mid - 1;
                // f[k] = f[k-1] + f[k-2],前面有f[k-1]个元素,可以进行拆分:f[k-1] = f[k-2] + f[k-3]
                // 在f[k-1]前继续查找,下次循环 mid = start + f[k-1 - 1] - 1
                k--;
            } else if (value > temp[mid]) {
                start = mid + 1;
                // f[k] = f[k-1] + f[k-2],后面有f[k-2]个元素,可以进行拆分:f[k-2] = f[k-3] + f[k-4]
                // 在f[k-2]前继续查找,下次循环 mid = start + f[k-2 - 1] - 1
                k -= 2;
            } else {
                // 正常情况返回mid,因为temp数组被补充过,原数组后面多了几个和end一样的元素,mid会超过数组的长度
                // 要返回mid和end小的那个,避免空指针异常
                if (mid <= end) {
                    return mid;
                } else {
                    return end;
                }
            }
        }
        return -1;
    }

    // 使用非递归方法得到一个斐波那契数列
    public static int[] fibonacci() {
        int maxSize = 20;
        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;
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值