zoukankan      html  css  js  c++  java
  • 二分算法 再次理解

    二分算法 再次理解

    详解二分查找算法

    这篇博客很详细介绍了二分算法的一些细节问题

    寻找一个数,也是最基本的二分搜索

    //代码示例如下
    int bsearch(int []nums, int target)
    {
        int left=0, right=nums.length-1;//这里的数组长度用法可以是其他的形式
        while(left<=right)
        {
            int mid = left + (right - left) / 2;
            if(num[mid] == target)
                return mid;
            else if(num[mid] > target)
                right = mid - 1;
            else left = mid + 1;
    	}
        return -1;//没有找到
    }
    

    寻找左侧边界的二分搜索

    这里的代码实现和lower_bound(begin,end+1, target)相同,都是找到第一个大于等于target的数组下标。

    int left_bound(int[] nums, int target)
    {
        if(nums.length == 0) return -1;
        int left = 0, right = nums.length; //注意这里的边界设置是左闭右开的。
        while(left < right)
        {
            int mid = left + (right - left) / 2;
            if(nums[mid] >= target)
                right = mid;//有边界进行压缩,依旧保持左开右闭的形式
            else left = mid+1;
    	}
        return left; //注意这里的left不一定是准确位置,这里的left有特殊含义
    }
    
    nums: 1 2 2 4
    index: 0 1 2 3

    如果使用这个左侧二分搜索2,那么将会返回1,表示在nums数组中有一个元素小于2,其他的类似。但是这样也存在一些问题,如果我们搜索1或者-1的时候,返回的值都是0,但是两者的含义是不同的,所以再收到结果后需要进行判断,以免出错。当然这里如果搜索的值为8的时候返回为值为4,也就是数组最后一个元素的下一个元素,这里也需要进行注意。

    寻找右侧边界的二分查找

    int right_bound(int[] nums, int target)
    {
        if(nums.length==0) return -1;
        int left = 0, right = nums.length;
        whlie(left < right)
        {
            int mid = left + (right - left) / 2;
            if(nums[mid] <= target)
                left = mid + 1; //左边界进行压缩
            else right=mid; //右边都是直接等于mid
    	}
        return left - 1;//这里有点不同,这里需要进行减一,特殊需要进行记忆。
    }
    

    这里的注意点就是返回值需要进行减一

    需要求一个边界,但是不知道是左边界还是右边界的情况

    这个是自己在做一个题的时候遇到的,详情参看这里:POJ 3685 Matrix

    //这里的nums元素也是有序的,但是nums可能不全是有效的,这时就需要我们使用这种方法
    int both_bound(int[] nums, int target)
    {
        int left=-1, right=nums.length, ans; //左右都开的区间内进行查找
        while(left+1 < right)
        {
            int mid = left + (right - left) / 2;
            //下面的两句话需要根据实际情况耳边
            //不变的是left和right都要直接等于mid
            if(nums[mid] >= target)		
            {						
                ans = mid;				
                left=mid;			
    		}
            else right=mid;
    	}
        return ans;
    }
    

    这篇文章是自己看到那篇博客的一些领会,详细参阅还是需要看看原文章,链接再最上面

    欢迎评论交流!
  • 相关阅读:
    装饰者设计模式
    Base64技术:把对象转变成字符串
    Android获取网络数据进行GZIP解压
    自定义Button成进度条
    Android:TextView最小行数设置
    介绍两个Android不常用的Drawable:GradientDrawable和 StateListDrawable
    Json介绍
    Android自定义XML属性
    Android手机图片适配问题
    AsyncTask
  • 原文地址:https://www.cnblogs.com/alking1001/p/12242408.html
Copyright © 2011-2022 走看看