二分查找总结

今天搜狐笔试,有一道算法题:给定排好序的成绩数组和及格分数线,要求找出及格的人数。

看到这个题就知道有坑,及格分数线的分数不一定出现在数组之中,而且分数还有可能有重复的,最普通的二分查找法根本没办法处理这种情况,最后这题答得不怎么样。

镇定思痛,看到一个还不错的总结:http://www.cnblogs.com/ider/archive/2012/04/01/binary_search.html

这里我也顺着思路来过一遍。

先说最普通的二分查找:

public static int bsearchWithoutRecursion(int array[], int low, int high, int target)
	{
	    while(low <= high)
	    {
	        int mid = (low + high)/2;
	        if (array[mid] > target)
	            high = mid - 1;
	        else if (array[mid] < target)
	            low = mid + 1;
	        else //find the target
	            return mid;
	    }
	    //the array does not contain the target
	    return -1;
	}

估计很多人都只会这种二分,这种二分只能查找出目标数存在于数组之中的情况。

下面介绍两种求最靠近目标数的上界和下界的二分查找方法:

public static int BSearchLowerBound(int array[], int low, int high, int target)
	{
	    //Array is empty or target is less than any every element in array
	    if(high < low  || target <= array[low]) return -1;
	    
	    int mid = (low + high + 1) / 2; //make mid lean to large side 
	    while (low < high)
	    {
	        if (array[mid] < target)  //需要寻找的array[mid] 比 target小
	            low = mid;
	        else
	            high = mid - 1;		//此时array[mid] >= target,mid不可能是最终结果,所以这里mid -1
	        
	        mid = (low + high + 1) / 2;
	    }

	    return array[mid];
	}

首先是求下界,在求上下界的时候要特别注意什么时候等于mid ,什么时候等于mid +- 1,其实理解了这个记起来还是很方便的,另外求下界的时候mid = ( low + high + 1) / 2,如果没有+1,在while里面可能就会出现死循环,比如low = 4 ,high = 5 ,然后判断时走 low = mid分支。

下面是求上界的二分查找方法:

public static int BSearchUpperBound(int array[], int low, int high, int target)
	{
	    //Array is empty or target is larger than any every element in array 
	    if(low > high || target >= array[high]) return -1;
	    
	    int mid = (low + high) / 2;
	    while (high > low)
	    {
	        if (array[mid] > target)
	            high = mid;
	        else
	            low = mid + 1;    		
	        mid = (low + high) / 2;
	    }
	    return mid;
	}

这里就不详细赘述了,原理和求上界类似。

今天笔试的这个题目其实求一次下界就可以做出来,掌握了这些以后才发现问题远没有自己考虑的那么麻烦!还是要好好修炼。

有些题目需要求出在某个区间[a,b]的数字个数,可以对a求下界,对b求上界,求出的两个mid值之差再减一就是结果,不过要考虑两个都返回 -1 index 的情况。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值