zoukankan      html  css  js  c++  java
  • 数组查找

    大纲

    1. 二分查找
    2. 插值查找
    3. 斐波那契查找

    tips:数组查找的前提是数组有序

    一、二分查找

      /**
         * 找到中间位置,然后递归前后两个部分
         */
        private static int binarySearch(int[] arr,int target,int begin,int end){
            if (end>=begin) {
                int mid = (begin+end)/2;
                if (arr[mid]>target) {
                    return binarySearch(arr,target,0,mid-1);
                }else if(arr[mid]<target){
                    return binarySearch(arr,target,mid+1,end);
                }else{
                    return mid;
                }
            }
            return -1;
        }

    二、插值查找

        /**
         * 中值有一定自适应性,适用于数值分布均匀的数组,比如等差数列
         */
        private static int insertSearch(int[] arr,int target,int begin,int end){
            if (end>=begin && target<=arr[end] && target>=arr[begin]) {
                int mid = begin+(end-begin)*(target-arr[begin])/(arr[end]-arr[begin]);
                if (arr[mid]>target) {
                    return binarySearch(arr,target,0,mid-1);
                }else if(arr[mid]<target){
                    return binarySearch(arr,target,mid+1,end);
                }else{
                    return mid;
                }
            }
            return -1;
        }

    三、斐波那契查找

        /**
         * 不用2分查找而是根据黄金分割点查找
         */
        private static int fibSearch(int[] arr,int target){
            int[] fib = getFib();//获取一个斐波那契数列
            int fibIndex = 0;
            while (fib[fibIndex] < arr.length) {
                fibIndex++;
            }
            //创建一个新数组,将原来的arr移动到新的数组中,新数组长度为斐波那契数列中的数,长度原来的长度的部分用原数组中最大的补齐
            int[] temp = new int[fib[fibIndex]];
            for (int i = 0; i < fib[fibIndex]; i++) {
                if (i>arr.length-1) {
                    temp[i] = arr[arr.length-1];
                }else{
                    temp[i] = arr[i];
                }
            }
            //查找
            int left = 0;
            int right = arr.length-1;
            while (right>=left) {
                //斐波那契数列F[K] = F[K-1] + F[K-2]
                //因此在前半段(较长的一段)中,再次分割点就是F[K-1],因后半段(较短的一段)中,再次分割点就是F[K-2]
                //建议自己画图,比较好理解
                int mid = left+fib[fibIndex-1]-1;
                if (temp[mid]>target) {
                    right = mid-1;
                    fibIndex-=1;
                }else if(temp[mid]<target){
                    left = mid+1;
                    fibIndex-=2;
                }else {
                    //每次查找都在后半部分,mid是有可能计算出来>right的(right一直是arr的最后一个元素指针)
                    //出现这种情况返回right即可,right因为后面都是arr[arr.length-1]的值
                    if (mid>right) {
                        return right;
                    }else{
                        return mid;
                    }
                }
            }
            return -1;
        }
        
        public static int[] getFib(){
            int[] fib = new int[20];
            fib[0] = 1;
            fib[1] = 1;
            for (int i = 2; i < fib.length; i++) {
                fib[i] = fib[i-1]+fib[i-2];
            }
            return fib;
        }
  • 相关阅读:
    数组中的逆序对★★
    把数组排成最小的数★★★
    丑数★★★
    整数中1出现的次数(从1到n整数中1出现的次数)
    连续子数组的最大和
    每两个字符串中插入字符串
    linux R环境安装以及注意事项
    JAVA调用R脚本 windwos路径下
    springboot 配置多数据源
    springboot 在配置文件写参数注入到类中
  • 原文地址:https://www.cnblogs.com/liuboyuan/p/14651101.html
Copyright © 2011-2022 走看看