首页 > 编程语言 >查找算法之斐波那契查找

查找算法之斐波那契查找

时间:2023-02-06 15:34:47浏览次数:42  
标签:arr int 之斐波 length 查找 pivot 那契

由来:

斐波那契数列:前两项之和等于第三项,假如下标为k,那么f[k] = f[k-1] + f[k-2]。如果将一条长为f[k]的线段分为两条线段,它们的长度分别为f[k-1]和f[k-2],这种分法很接近黄金分割比。斐波那契查找由此而来。

 简介:

如果一个数组的长度是f[k],那么就可以把它分为两个子数组,一个的长度是f[k-1],另一个的长度是f[k-2]。例:k = 5,f[k] = 8,f[k-1] = 5,f[k-2] = 3

 如果这样分割,那么中轴的下标pivot = left + f[k-1] - 1 =  0 + 5 - 1 = 4

 斐波那契查找原理与二分查找相同,只是不是折半划分子数组,而是按照黄金分割的比例进行划分。例子如下:

 代码:

    /**
     * 斐波那契查找
     * @param arr               从小到大的有序数组
     * @param fibonacciLength   斐波那契数组的长度,保证f[fibonacciLength - 1] > arr.length
     * @param value             目标值
     * @return
     */
    public static List<Integer> fibonacciSearch(int[] arr, int fibonacciLength, int value) {
        if (arr == null || arr.length == 0) {
            return Collections.emptyList();
        }
        //得到一个斐波那契数组,长度为k
        int[] fibonacciArray = createFibonacciArray(fibonacciLength);
        //得到k的值,使得fibonacciArray[k] >= arr.length
        int k = 0;
        while (arr.length > fibonacciArray[k]) {
            k++;
        }
        //如果arr.length < fibonacciArray[k],那么就将数组的长度扩充到fibonacciArray[k],用数组最大的值进行填充
        int[] newArr = Arrays.copyOf(arr, fibonacciArray[k]);
        for (int i = arr.length; i < newArr.length; i++) {
            newArr[i] = arr[arr.length - 1];
        }
        //中轴下标
        int pivot;
        //左索引
        int left = 0;
        //右索引
        int right = arr.length - 1;
        //与目标值相同的下标集合
        List<Integer> result = new ArrayList<>(arr.length);
        //利用二分查找的原理去查找目标值
        while (left <= right) {
            pivot = left + fibonacciArray[k-1] - 1;
            if (value < newArr[pivot]) {
                //往左边找
                right = pivot - 1;
                k -= 1;
            } else if (value > newArr[pivot]) {
                //往右边找
                left = pivot + 1;
                k -= 2;
            } else {
                //目标值等于中轴值,如果中轴下标指向的是扩充的值,那么pivot = arr.length - 1
                if (pivot > arr.length - 1) {
                    pivot = arr.length - 1;
                }
                //向左向右看看紧挨着的值有没有等于arr[pivot],如果有,将它们的下标也返回
                int temp = pivot;
                while (temp >= 0 && arr[temp] == arr[pivot]) {
                    //向左查找
                    result.add(temp);
                    temp--;
                }
                temp = pivot + 1;
                while (temp <= arr.length - 1 && arr[temp] == arr[pivot]) {
                    //向右查找
                    result.add(temp);
                    temp++;
                }
                return result;
            }

        }
        //没有找到
        return Collections.emptyList();
    }

    /**
     * 生成斐波那契数组
     * @param fibonacciLength  数组的长度
     * @return
     */
    private static int[] createFibonacciArray(int fibonacciLength) {
        int[] fibonacciArray = new int[fibonacciLength];
        fibonacciArray[0] = 1;
        fibonacciArray[1] = 1;
        for (int i = 2; i < fibonacciArray.length; i++) {
            fibonacciArray[i] = fibonacciArray[i - 1] + fibonacciArray[i - 2];
        }
        return fibonacciArray;
    }

 

标签:arr,int,之斐波,length,查找,pivot,那契
From: https://www.cnblogs.com/xueseng/p/17095562.html

相关文章

  • sql语句重复数据的查找和删除
    一、查找重复记录1.查找全部重复记录单字段:Select*From表Where重复字段In(Select重复字段From表GroupBy重复字段HavingCount(*)>1)多字段:selectidfrom......
  • 《剑指Offer》-4-二维数组中查找/力扣-240-搜索二维数组Ⅱ
    从最后一列的第一个数字开始比较,依次倒数第二列第一个数字、倒数第三列...找到第一个<=target的数字,这样可以将范围缩小到一列然后用二分查找快速判断目标元素有没有......
  • 《剑指Offer》-53-在排序数组中查找数字/力扣-34
    Ⅰ统计一个数字在排序数组中出现的次数 intsearch(vector<int>&nums,inttarget){ intcount=0; for(intnum:nums){ if(num==target)count++; ......
  • [数据结构] 二分查找 (四种写法)
    二分查找二分查找二分查找(BinarySearch)也叫作折半查找,前提是查找的顺序结构是有序的,我们一般在数组上进行二分查找。二分查找就好像猜数字大小游戏一样。假设要数字目......
  • 4.7二叉查找树使数据搜索更有效
    二叉查找树是指在链表的基础上往数组中追加元素时,考虑到数据的大小关系,将其分成左右两个方向的表现形式。例如,假设我们事先把50这个值保存到了数组中。那么,如果接下来的值......
  • 二分查找法
    publicstaticintdichotomySearch(int[]array,inta){System.out.println("正在执行方法");intstart=0;intlength=array.length-1;......
  • python基础:函数参数、名称空间、名称空间存活周期极其作用域、名字的查找顺序
    目录一、函数参数一、位置参数位置形参位置实参二、默认参数(关键字参数)关键字形参关键字实参三、可变长形参(可变长度的形参)四、可变长实参(可变长度的实参)五、命名关键字参......
  • 【算法】二分法 ② ( 排序数组中查找目标值 | 二分法的经典写法 | 在排序数组中查找元
    文章目录​​一、排序数组中查找目标值(二分法的经典写法)​​​​二、在排序数组中查找元素的最后一个位置(二分法的通用模板)​​一、排序数组中查找目标值(二分......
  • js之查找和过滤|2-4
    通常情况下选择器可以直接定位到我们想要的元素,但是,当我们拿到一个jQuery对象后,还可以以这个对象为基准,进行查找和过滤。最常见的查找是在某个节点的所有子节点中查找,使用​......
  • 查找和过滤4
    通常情况下选择器可以直接定位到我们想要的元素,但是,当我们拿到一个jQuery对象后,还可以以这个对象为基准,进行查找和过滤。最常见的查找是在某个节点的所有子节点中查找,使用​......