本文介绍了二分查找算法的原理和实现方法。这是一种高效的搜索算法,通过不断缩小搜索范围,将查找目标与中间元素进行比较,从而快速定位目标元素的位置。二分查找真的是简单但是最容易出错的算法,我们来通过leeetcode的一道题来巩固这个算法。

题目:

来源:leetcode第34题,难度为中等

思路:

看到数组是有序的,瞬间想到二分算法,需要找到两个位置,那么就用两次二分算法,分别找到开始位置和结束位置。

开始位置:

1.定义left在数组最左端,right在数组最右端

2.每次取中间mid,如果中间的值小于目标值,就让left=mid+1,否则就让right=mid,一直循环

3.当left=right的时候,就是结果

4.判断left位置的值是否等于目标值,如果相等,left就是开始位置,用begin记录left,否则,结果不存在,返回[-1,-1]

结束位置

总体来说和开始位置的算法差不多,有一些小区别

1.left此时已经找到开始位置,所以left不用动,让right在数组最右端

2.每次取中间mid,如果中间的值小于等于目标值,就让left=mid,否则就让right=mid-1,一直循环

3.当left=right的时候,就是结果

4.返回数组[begin,right]

代码实现:

class Solution {
    public int[] searchRange(int[] nums, int target) {
        int left=0,right=nums.length-1,begin=0;
        int []ret={-1,-1};
        //判断数组是否为空
        if(nums.length==0)
        return ret;
        //找左端点
        while(left<right)
        {
            int mid=left+(right-left)/2;
            if(nums[mid]<target)
            left=mid+1;
            else
            right=mid;
       }
       if(nums[left]!=target)
        return ret;
        else
        begin=left;//标记左端点
        //找右端点
        right=nums.length-1;
       while(left<right)
        {
            int mid=left+(right-left+1)/2;
            if(nums[mid]<=target)
            left=mid;
            else
            right=mid-1;
       }
       ret[0]=begin;ret[1]=right;
       return ret;
    }
}

总结:

虽然思想不难,但还是踩了好多坑:

1.判断条件是left<right,而不是left<=right

在left等于right的时候就已经是结果了,此时如果再判断,就会死循环。

2.(right-left)/2和(right-left+1)/2的区别

这两个的区别就是一个在中间偏左,一个在中间偏右,在寻找左端点的时候必须要使用第一种,寻找右端点的时候,必须要使用第二种,否则都会死循环。

 

阅读上一篇:使用html和css实现”跳动的心“