二分查找算法(递归以及while)

二分查找

在工作中,很多小伙伴应该会遇到这样的需求,在有序的数组中查找指定元素,比如数组 nums = [1, 3, 5, 7, 8, 11, 19, 23, 27, 33, 45, 55, 67, 98] 中查找 目标数据 8,如果找到就返回该目标数据在数组中的下标索引的位置。

算法描述

二分查找的思想也比较简单,判断数组中的中间元素和目标数据进行比较,如果相等,也就返回数组中的中间元素,如果小于中间元素的话,也就说明需要查找的元素在数组中的前半部分,如果大于中间元素的话,说明在需要查找的元素在数组中的后半部分。
以上描述的是不是有点饶头,那么我们可以通过以下的图示表示二分查找的整个过程。
在这里插入图片描述

算法实现while 以及 递归 实现

package com.sh.study.search;

/**
 * 二分查找,查找指定数据,并返回目标数据在数据中的位置,-1 表示数组中没有指定的数据
 *
 * @Author zhouwenchen
 * @Data 2020/8/13/15
 **/
public class BinarySearch {

    /**
     * 二分查找 指定目标的数据
     * 使用 while 循环实现
     *
     * @param nums
     * @param target
     * @return
     */
    public static int binarySearch(int[] nums, int target) {
        if (nums == null) {
            return -1;
        }
        int low = 0;
        int high = nums.length - 1;
        while (low <= high) {    // 这边注意要写成 <= ,不然的话,单个元素会匹配不成功的
            int mid = (low + high) / 2;
            if (nums[mid] == target) {
                return mid;
            } else if (nums[mid] < target) {
                low = mid + 1;
            } else {
                high = mid - 1;  // 之前错误的写成了 high = high - 1;
            }
        }
        return -1;
    }

    /**
     * 使用递归实现
     *
     * @param nums
     * @param target
     * @return
     */
    public static int binarySearch0(int[] nums, int start, int end, int target) {
        if (nums == null || start > end) {
            return -1;
        }
        int mid = (start + end) >> 1;
        if (nums[mid] == target) {
            return mid;
        } else if (nums[mid] > target) {
            return binarySearch0(nums, start, mid - 1, target);
        } else {
            return binarySearch0(nums, mid + 1, end, target);
        }
    }

    public static void main(String[] args) {
        int[] nums = {1, 3, 5, 7, 8, 11, 19, 23, 27, 33, 45, 55, 67, 98};
        int target = 27;
        System.out.println("location is " + binarySearch(nums, target));
        System.out.println("location is " +  binarySearch0(nums, 0, nums.length - 1, target));
    }
}

算法时间复杂度分析

我们每次都可以将目标数组缩短为原数组的一半,
假设目标数组的大小是n,也就是 n ,n/2,n/4…n/2^k 求和可以得到
其中 n/2k=1 时,k 的值就是总共缩小的次数
我们可以求得 k=log2n,所以时间复杂度就是 O(logn)

算法的应用场景

1:有序数组

二分查找,主要用于有序数组中查找指定的数据。所以,二分查找需要在有序的数组中查找。
换句话,如果数据是无序的 ,或者不是以数组存储的有序数据也是不特别适用的

2:数据量适中

如果数据量太少的情况,可以直接使用遍历就好了,没必要使用二分查找,
如果数据量比较大的话,也不适用,因为二分查找主要底层使用数组存储,数组需要使用一段连续的内存空间,如果数据量太大的话,内存中可能没有那么大的连续内存。基于此,那么是否有小伙伴想着说,那我们用链表存储,就不需要连续的内存空间了嘛?但是如果使用链表存储的话,那么每次遍历的时间复杂度就变成了O(n),相比于数组的查找数据的时间复杂度O(1)相比来说,不合适

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值