• 二分、值插、斐波那契查找


    二分查找

    二分查找的思路分析

    • 首先确定该数组的中间的下标

      • mid= (left +right)/ 2
    • 然后让需要查找的数findVal和a[mid]比较

      • findVal> ar[mid],说明你要查找的数在mid的右边,因此需要递归的向右查找
      • findVal< ar[mid],说明你要查找的数在mid的左边,因此需要递归的向左查找
      • findVal== ar[mid]说明找到,就返回
    • 什么时候我们需要结束递归。

      • 找到就结束递归
      • 递归完整个数组,仍然没有找到findVal,也需要结束递归当left>right就需要退出

    使用二分查找的前提是该数组是有序的。

    查找一个不重复的值

    public static void main(String[] args) {
        int[] arr = {1,23,45,67,79,90,212}
        int i = erFenSearch(arr, 0, arr.length-1, 1);
        System.out.println(i);
    }
    
    public static int erFenSearch(int[] arr,int left, int right,int findValue){
        if (left > right){
            return -1;
        }
        int mid = (left + right) / 2 ;
        int midValue = arr[mid];
        if (findValue < midValue){
            return erFenSearch(arr, left, mid - 1, findValue);
        }else if (findValue > midValue){
            return erFenSearch(arr, mid + 1, right, findValue);
        }else {
            return mid;
        }
    }
    

    查找所有的下标

    public static void main(String[] args) {
        int[] arr = {1,23,46,89,89,89,89,122,165,267};
        List<Integer> list = erFenSearch1(arr, 0, arr.length - 1, 89);
        System.out.println(list);
    }
    
    public static List<Integer> erFenSearch1(int[] arr, int left, int right, int findValue){
        if (left > right){
            return new ArrayList<Integer>();
        }
        int mid = (left + right) / 2 ;
        int midValue = arr[mid];
        if (findValue < midValue){
            return erFenSearch1(arr, left, mid - 1, findValue);
        }else if (findValue > midValue){
            return erFenSearch1(arr, mid + 1, right, findValue);
        }else {
            List<Integer> list = new ArrayList<Integer>();
            int temp = mid - 1;
            while (true){
                if (temp < 0 || arr[temp] != findValue){
                    break;
                }
                list.add(temp);
                temp--;
            }
            list.add(mid);
            temp = mid + 1;
            while (true){
                if (temp > arr.length - 1 || arr[temp] != findValue){
                    break;
                }
                list.add(temp);
                temp++;
            }
            return list;
        }
    }
    

    插值查找

    要求数组有序,适用于数据分布均匀的情况;

    image-20200601101014271

    public static void main(String[] args) {
        int[] arr = new int[100];
        for (int i = 0; i < arr.length; i++) {
            arr[i] = i + 1;
        }
        int i = insertValueSearch(arr, 0, arr.length - 1, 99);
        System.out.println(i);
    
    }
    
    public static int insertValueSearch(int[] arr,int left, int right,int findValue){
        if (left > right || findValue < arr[0] || findValue > arr[arr.length-1]){
            return -1;
        }
        int mid = left + (right - left) * (findValue - arr[left]) / (arr[right] - arr[left]);
        int midValue = arr[mid];
        if (findValue > midValue){
            return insertValueSearch(arr, mid + 1, right, findValue);
        }else if (findValue < midValue){
            return insertValueSearch(arr, left, mid - 1, findValue);
        }else {
            return mid;
        }
    }
    

    斐波那契查找

    斐波那契数列{1,1,2,3,5, 8, 13,21, 34, 55}发现斐波那契数列的两个相邻数的比例,无限接近黄金分割值0.618

    核心f(k) =f(k - 1) + f(k - 2) ====>>> f(k) - 1 =( f(k - 1) - 1)+(f(k - 2) - 1) + 1

    public class FibSearch {
        public static int maxSize = 20;
        public static void main(String[] args) {
            int[] arr = {1,8,10,89,1000,1024};
            System.out.println(fibSearch(arr,1));
        }
        //制造斐波那契数列
        public static int[] fib(){
            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;
        }
        //斐波那契查找方法
        public static int fibSearch(int[] arr,int key){
            int low = 0;
            int high =arr.length - 1;
            int k = 0;//表示斐波那契分割数值的下标
            int mid = 0;
            //获取斐波那契数列
            int[] f = fib();
            //获取到比arr大的斐波那契分割数值的下标
            while (high > f[k] - 1){
                k++;
            }
            //因为f[k]值可能大于arr的长度,因此我们需要使用Arrays类,构造一个新的数组,并指向temp[]不足的部分会使用最大值填充
            int[] temp = Arrays.copyOf(arr,f[k]);
            for (int i = high + 1; i < temp.length; i++) {
                temp[i] = temp[high];
            }
    
            while (low <= high){
                mid = low + f[k - 1] - 1;
                if (key < temp[mid]){
                    high = mid - 1;
                    k--;//f(k) =f(k - 1)高 + f(k - 2)低
                }else if (key > temp[mid]){
                    low = mid + 1;
                    k -= 2;//f(k) =f(k - 1)高 + f(k - 2)低
                }else {
                    if (high < mid){
                        return high;
                    }else {
                        return mid;
                    }
                }
            }
            return -1;
        }
    }
    
  • 相关阅读:
    ios开发之 -- 自动轮播图创建
    swift开发之 -- 自动轮播图(UIScrollView+UIPageControl+Timer)
    HTML5开发之 -- 模态突出窗(bootstrap)
    ios开发之--UICollectionView的使用
    ios开发之--判断奇偶数
    swift开发之 -- ? 和 ! 的作用
    swift开发之--UISearchBar的使用/UISearchController的使用
    swift开发之--报错:Class "***ViewController" has no initializers
    Android开发相关
    沁园春·雪
  • 原文地址:https://www.cnblogs.com/chaostudy/p/13024548.html
Copyright © 2020-2023  润新知