zoukankan      html  css  js  c++  java
  • 查找算法

    1.二分查找

    二分查找必须对有序数组进行,每次先找到中间值进行比较,若大于当前值则向后继续按此方法找,若小于当前值则向前继续按此方法找。

    二分查找的思路:

    1.首先确定数组中间值:

    mid = (left + right) / 2;

    2.然后比较中间值mid和要查找的值num大小;

    2.1若num>arr[mid],则向右递归;

    2.2.若num<arr[mid],则向左递归;

    2.3.若num=arr[mid],则返回值;

    3.当left>right时结束递归;

    package com.sratct.search;
    
    import java.util.ArrayList;
    import java.util.List;
    
    /**
     * 二分查找
     */
    public class BinarySearch {
        public static void main(String[] args) {
           int[] arr = {1, 5, 20, 60,60, 81};
             System.out.println(binarySearch(arr,0, arr.length-1, 61));
            System.out.println(binarySearch1(arr,0, arr.length-1, 61));
        }
    
        /**
         * 在一个有序数组中查找到一个数并返回下标
         * @param arr
         * @param left
         * @param right
         * @param num
         * @return
         */
        public static int binarySearch(int[] arr, int left, int right, int num) {
            int mid = (left + right) / 2;
            if (left <= right) {
    
                if (num < arr[mid]) { // 需要查找的值小于中间值
                    // 左边递归
                    return binarySearch(arr, left, mid-1, num);
                } else if (num > arr[mid]) {  // 需要查找的值大于中间值
                    // 右边递归
                    return binarySearch(arr,mid+1, right, num);
                } else {
                    return mid;
                }
            }
            return -1;
        }
    
        /**
         * 在一个有序数组中查找一个数并返回所有相同的数的下标
         * @param arr
         * @param left
         * @param right
         * @param num
         * @return
         */
        public static ArrayList<Integer> binarySearch1(int[] arr, int left, int right, int num) {
            int mid = (left+right)/2;
            if (left <= right) {
                if (num < arr[mid]) { // 需要查找的值小于中间值
                    // 左边递归
                    return binarySearch1(arr, left, mid-1, num);
                } else if (num > arr[mid]) {  // 需要查找的值大于中间值
                    // 右边递归
                    return binarySearch1(arr,mid+1, right, num);
                } else {
                    // 当找到值以后,向左向右查找到相同的值,下标存入集合
    
                    List<Integer> integers = new ArrayList<>();
                    // 向左边查找
                    int temp = mid - 1;
                    while (true) {
                        if (temp < 0 || arr[temp] != num) {
                            break;
                        }
                            integers.add(temp);
                            temp -=1;  //temp 左移
                    }
    
                    // 中间值
                    integers.add(mid);
    
                    // 右边
                    temp = mid + 1;
                    while (true) {
                        if (temp > arr.length-1 || arr[temp] != num) {
                            break;
                        }
                        integers.add(temp);
                        temp +=1;  //temp右移
                    }
                    return (ArrayList<Integer>) integers;
                }
            }
           return null;
        }
    }
    

    2.插值查找

    1)插值查找类似于二分查找,不同的是插值查找每次自适应mid处开始查找;

    2)左边所有left,右边所有right,key为要查找的值num;

    二分查找和插值查找公式:

    mid = (left + high) / 2 = left + 1/2(right-left); // 二分查找

    mid = left + ((num - arr[left]) / (arr[right] - arr[left]) )* (right - left); //插值查找

    package com.sratct.search;
    
    /**
     * 插值查找
     */
    public class InsertValueSearch {
        public static void main(String[] args) {
            int[] arr = new int[100];
            for (int i=0; i<arr.length; i++) {
                arr[i] = i+1;
            }
            System.out.println(insertValueSearch(arr,0,99,0));
        }
    
        // 插值查找
        public static int insertValueSearch(int[] arr, int left, int right, int num) {
    
            // 防止数组越界:num > arr[0] || num > arr[arr.length-1]
            if (left <= right || num > arr[0] || num > arr[arr.length-1]) {
                int mid = left + ((num - arr[left]) / (arr[right] - arr[left])) * (right - left);
                if (num > arr[mid]) {
                    return insertValueSearch(arr, mid + 1, right, num);
                } else if (num < arr[mid]) {
                    return insertValueSearch(arr, left, mid - 1, num);
                } else {
                    return mid;
                }
            }
            return -1;
        }
    }
    

    3.斐波那契(黄金分割法)查找算法

    1)黄金分割点指把一条线段分割为两部分,使其中一部分与全长之比等于另一部分与这部分之比。取前三位近似数值为0.618。

    2)斐波那契数列{1,1,2,3,5,8,13,21,34,55}发现两个相邻的数之比近似为0.618。

    3)工作原理:

    斐波那契查找原理与前面两种相似,仅仅改变中间结点(mid)位置,此时mid为黄金分割点附近,

    即mid = left + F(k-1)-1 (F为斐波那契数列),如图

    对F(k-1)-1的理解:

    1)有斐波那契数列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 = left + F(k-1) -1

    1. 类似的每一段都可以用相同方式分割;

    3)但是顺序表的长度不一定为F(k)-1,所以需要将原来的顺序表长度n增加至F(k)-1,这里的k值只要能使得F(k)-1恰好大于等于n即可,有下面代码得到,顺序表长度增加后,新增的位置(从n+1到F(k)-1位置),都赋为n位置的值即可
    while(n>flib(k)-1)

    k++;

  • 相关阅读:
    [Angular2 Form] Build Select Dropdowns for Angular 2 Forms
    [Angular2 Form] Create Radio Buttons for Angular 2 Forms
    [Angular2 Router] Exiting an Angular 2 Route
    [Angular2 Router] Optional Route Query Parameters
    JS 实现地区,省份,城市,县区4级联动
    Linux web工程部署远程必备软件安装
    [置顶] 白话01背包
    APUE读书笔记-第17章-高级进程间通信
    UVA 10779 Collectors Problem(最大流)
    (二) win8+XAML Binding(数据绑定)
  • 原文地址:https://www.cnblogs.com/cqyp/p/14718411.html
Copyright © 2011-2022 走看看