查找算法

插值查找
插值查找算法类似于二分查找,不同的是插值查找每次从自适应mid处开始查找。
将折半查找中的求mid索引的公式, left表示左边索引, right表示右边索引.
int mid = left + (right - left) * (findVal - arr[left]) / (arr[right] - arr[left])
代码实现

    /**
     *  插值查找
     *  注意:插值查找要求数组是有序的
     * @param arr 数组
     * @param left 左边索引
     * @param right 右边索引
     * @param findVal 查找的值
     * @return
     */
    public static int insertValueSearch(int[] arr,int left,int right,int findVal){

        //注意findVal < arr[0] || findVal > arr[arr.length - 1] 必须需要
        //否则得到的mid值可能越界;
        if(left > right || findVal < arr[0] || findVal > arr[arr.length - 1]){
            return -1;
        }
        //求出mid,自适应写法
        int mid = left + (right - left) * (findVal - arr[left]) / (arr[right] - arr[left]);
        int midVal = arr[mid];
        if(findVal > midVal){
            return insertValueSearch(arr,mid + 1,right,findVal);
        }else if(findVal > midVal){
            return insertValueSearch(arr,left, mid - 1,findVal);
        }else{
            return mid;
        }
    }

二分查找的思路分析
使用二分查找前提是 必须是有序的数组
1.首先确定该数组的中间的下标mid = (left+right)/ 2
2.然后让需要查找的数findval和arr[mid]比较
3. 1 findval>arr[mid],说明你要查找的数在mid的右边,因此需要递归的向右查找2.2 findval<arr[mid],说明你要查找的淡在mid的左边,因此需要递归的向左查找2.3 findvalmm arr[mid]说明找到,就返回

什么时候我们需要结束递归
1)找到就结束递归
2)递归完整个数组,仍然没有找到需要查找的值,也需要结束递归。当左索引 > 右索引就需要退出
代码实现

   /**
     *  二分查找
     *  注意:二分查找的前提 必须是该数组是有序的
     * @param arr 数组
     * @param left 左边索引
     * @param right 右边索引
     * @param findVal 查找的值
     * @return
     */
    public static ArrayList<Integer> binarySearchYH(int []arr, int left, int right, int findVal){
        //当 left > right时,说明递归整个数组,但是没有找到
        if(left > right){
            return new ArrayList<>();
        }
        int mid = (left + right) / 2;
        int midVal = arr[mid];

        if (findVal > midVal){ //向右递归
            return binarySearchYH(arr,mid + 1,right,findVal);
        } else if(findVal < midVal){ //向左递归
            return binarySearchYH(arr,left,mid - 1,findVal);
        } else {
            //思路分析
            //在找到mid 素引值,不要马上返回
            //向mid索引值的左边扫描,将所有满足findVal的元素的下标,加入到集合ArrayList
            //向mid索引值的右边扫描,将所有满足findVal的元素的下标,加入到集合ArrayList
            //将Arraylist返回
            ArrayList<Integer> list = new ArrayList<>();
            //向左扫描所有满足条件的加入集合
            int temp = mid - 1;
            while (true){
                //当向左扫描时,下标小于0时或者值与查找值不符时退出
                if (temp < 0 || arr[temp] != findVal){
                    break;
                }
                list.add(temp);
                temp -= 1;//向左查找 左移
            }
            list.add(mid);

            //向右扫描所有满足条件的加入集合
            temp = mid + 1;
            while (true){
                //当向右扫描时,下标大于数组长度-1时时或者值与查找值不符时退出
                if (temp > arr.length - 1 || arr[temp] != findVal){
                    break;
                }
                list.add(temp);
                temp += 1;//向右查找右移
            }
            return list;
        }
    }
posted @ 2022-03-29 21:04  橙香五花肉  阅读(23)  评论(0编辑  收藏  举报