二分查找你真的会吗?

1.什么是二分查找
二分查找(Binary Search)算法,也被称为折半查找算法。算法的思想也是非常的简单。(此篇为学习完极客课程结构与算法总结而做,如有雷同纯属抄袭),二分查找是一种极其简单的快速查找算法,生活中随处可见 ,例如我们之前都会遇到的猜数字的问题,用的就是二分查找到思想。闲话不多说直接上代码。

	public static int binarySearch(int[] arr,int n,int k){
        int low = 0;
        int high = n-1;
        while (low<=high){
            //防止low 和high太大 超出 int的范围 注意前边的运算必须要用 括号 扩 起来
            int mid = ((high-low)>>1) + low;
            //int mid = (high+low)>>1;
            if(arr[mid]<k){
                low = mid+1;
            }else if(arr[mid]>k){
                high = mid-1;
            }else {
                return mid;
            }
        }
        return -1;
    }

上述代码就是一个简单的二分查找算法的实现。对于一个二分查找算法需要注意的主要有三点。
1.循环退出条件
只有当low<=high的时候才跳出循环,因为k=low=high的时候是可以继续循环的。
2.mid的取值
mid的取值我们都会,(low+high)/2 就可以但是当low和high都是特别大的数的时候这个值就会超出int的范围所以我们使用代码中的方法防止mid超出int范围.
3.low和high的跟新

2.二分查找的时间空间复杂度
我们分析一个算法的好坏,首先就是要分析他的时间空间复杂度,那么二分查找的时间空间复杂度是多少呢? 假设需要查找的数据是n,每次查找的区间区间的变化大小为:n,n/2,n/4,n/8,n/2^m, 这是一个等比数列。
其中n/2^m=1的时候可以算的m=logn,所以时间复杂度就是O(logn).当然他的空间复杂度就很容易分析为O(1)。我们可以想象到即使是一个特别特别大的数组,用二分查找发查找一个数据,也只是很少的次数就可以查找出来这个数据。

3.二分查找的迭代实现
二分查找的思想其实非常的类似于分治的思想,针对于分治思想的算法我们都可以使用迭代来实现的。代码如下:

 public static int binarySearchUseRecursion(int[] arr,int n,int k){
        int low = 0;
        int high = n-1;
        return searchInterally(arr,low,high,k);
    }

    /**
     * 迭代实现 二分查找
     * @param arr
     * @param low
     * @param high
     * @param k
     * @return
     */
    private static int searchInterally(int[] arr,int low, int high,int k) {
        if(low>high)return -1;
        int mid = ((high-low)>>1) + low;
        if(arr[mid]==k){
            return mid;
        } else if(arr[mid]<k){
            searchInterally(arr,mid+1,high,k);
        }else if(arr[mid]>k){
            searchInterally(arr,low,mid-1,k);
        }
        return -1;
    }

4.二分查找的使用场景与局限性
二分查找的时间复杂度非常非常的低,甚至有时候比O(1)的速度更快,那么什么时候适合用二分查找呢。

  1. 二分查找需要的数据结构必须是数组
    如果换成链表时间复杂度会退化到O(n).如果换成链表时间复杂度会退化到O(n).
  2. 二分查找的数据是有序的
    不仅仅需要数据是有序的,而且针对二分查找所查询的数据必须是趋向于静态的数据,就是不会频繁的修改的数据,如果是频繁修改的数据,那么不停的进行排序,维护有序的成本都是很高的。如果是较少次数的排序我们是可以进行时间复杂度的均摊的。
  3. 数据量太小不适合
    当数据量特别小的时候,顺序查询其实是和二分查找的速度差不多的。但是也有例外的情况,当每次查询的消耗的时间资源特别高的时候还是推荐使用BinarySearch。
  4. 数据量太大也不适合
    我们都知道二分查找需要的数据结构是数组,当数组存储的数据特别大的时候,由于数组占用的是一段连续的存储空间。所以对内存的损耗还是非常大的。

5.利用二分查找处理问题?

  1. 假设我们有1000万数据,每个数据占八个字节,如何设计数据结构和算法,快速判断某个整数是否出现在这一千万数据当中?要求实现这个功能占用的内存最多不要超过100MB?
  2. 如何自己变成实现去一个数的平方根要求精确六位小数?
    总结
    二分查找的思想理解起来非常的简单,就是每次将查找范围缩小为原来的一半,直到查到我们需要的数据,或者区间缩小为0。
    最后关于文章题目的答案和复杂的二分查找我会在下一篇文章中给出。(题目来源极客时间)

猜你喜欢

转载自blog.csdn.net/weixin_39034379/article/details/83548079