• 二分查找及其应用


    二分查找是一种非常经典的查找算法,其应用场景也非常多,算法思路清晰,但是其效率很高。

    /**
      * 二分查找
      * 如果数组中存在目标值,返回其对应下标
      * 如果数组中不存在目标值,则返回-1
      * */
    public static int binarySearch(int[] arr,int target){
        int low = 0;
        int high = arr.length-1;
        while (low<=high){
            int mid = low+(high-low)/2;
            if(target<arr[mid]){
                high = mid-1;
            }
            else if(target>arr[mid]){
                low = mid+1;
            }
            else{
                return mid;
            }
        }
        return -1;
    }

    注意点:时间复杂度为O(logN),计算mid有两种方式,1) mid=(low+high)/2,2) mid=low+(high-low)/2,low+high有可能出现加法溢出,最好用第二种方式。3) 循环条件有两种方式,low<high和low<=high,如果是low<high,那么相应的high的赋值表达式就是high=mid,如果是low<=high,相应的high的赋值表达式就是high=mid-1。

    应用一:求开方

        求一个数num的算术平方根sqrt,一个数num的算术平方根sqrt一定在0~num/2之间,并且满足sqrt=num/sqrt,可以利用二分查找在0~num/2之间查找sqrt。

    public static int mysqrt(int x){
    if (x<=1){
    return x;
    }
    int low=1;
    int high=x/2;
    while (low<=high){
    int mid=low+(high-low)/2;
    int sqrt=x/mid;
    if (sqrt<mid){
    high=mid-1;
    }
    else if(sqrt>mid){
    low=mid+1;
    }
    else{
    return mid;
    }
    }
    return high;
    }

    应用二:摆硬币

        给定n个硬币,在第i行摆i个硬币,求总共可以摆满多少行,可以利用二分查找。

    public static int arrangeCoins(int n) {
        int low = 0;
        int high = n;
        while(low <= high){
            int mid = low + (high - low) / 2;
            long x = mid * (mid + 1L) / 2;
            if(x == n){
                return mid;
            }
            else if(x < n){
                low = mid + 1;
            }
            else high = mid - 1;
        }
        return high;
    }

    应用三:有序数组的 single element

        在一个有序数组中只有一个元素出现一次,其余元素均出现2次,找出这个元素,可以利用二分查找。

    public static int singleNoDuplicate(int[] arr){
        int low=0;
        int high=arr.length-1;
        while (low<high){
            int mid = low+(high-low)/2;
            if (mid%2==1){
                mid--;
            }
            if(arr[mid]==arr[mid+1]){
                low=mid+2;
            }
            else{
                high=mid;
            }
        }
        return arr[low];
    }
  • 相关阅读:
    eth0&nbsp;no&nbsp;such&nbsp;device(reload)
    wince驱动开发入门
    如何在Linux中添加新的系统调用
    嵌入式Linux启动优化手记2&nbsp;U…
    关于uboot的一些优化
    Yaffs2根文件系统制作
    kernel下制作动态logo
    linux&nbsp;dev/dsp&nbsp;声卡学习笔记
    【JDK8】Java8 优雅的异步调用API CompletableFuture
    每周总结:2019年12月第5周
  • 原文地址:https://www.cnblogs.com/earthhouge/p/8849773.html
Copyright © 2020-2023  润新知