二分法及二分法的变形

常规二分法

public int bSearch(int[] a, int n, int value){
	int low = 0;
	int high = n-1;

	while (low <= high) {
		int mid = (low + high)/2;
		if (a[mid] == value) {
			return mid;
		} else if (a[mid] < value) {
			low = mid + 1;
		} else {
			high = mid - 1;
		}
	}
	return -1;
}

注意循环条件

注意是 low <= high,而不是 low < high。
当low = high的时候,查找区间内还有一个数字需要判断,如果循环条件是<的话,那么这种情况会退出循环返回-1。
例如[1,2,3]查2的情况

mid取值

mid=(low+high)/2的情况,当数字足够大时,有可能产生溢出的情况。应写成mid = low + (high - low)/2。
为了进一步优化性能,可采用位运算,改为mid = low + ((high - low)/2>>1)

low和high的更新

low=mid+1,high=mid-1。注意这里的 +1 和 -1,如果直接写成 low=mid 或者 high=mid,就可能会发生死循环。
例如[1,5,7]查4的情况。

查找第一个值等于给定值的元素

public int bSearch(int[] a, int value) {
	int left = 0;
	int right = a.length - 1;
	// 挤压右边界,返回左边界
	while (left <= right) {
		int mid = left + ((high - low) >> 1);
		if (a[mid] >= value) {
			high = mid -1;
		} else {
			low = mid + 1;
		} 
	}
	// 可能会右边越界,也可能数组中无目标数,需要做判断
	if (low < n && a[low] == value) {
		return low;
	}
	return -1;
}

查找最后一个值等于给定值的元素

    public static int bSearch(int[] a, int n, int value) {
        int low = 0;
        int high = n - 1;
        // 挤压左边界,返回右边界
        while (low <= high) {
            int mid = high - ((high - low) >> 1);
            if (a[mid] <= value) {
                low = mid + 1;
            } else {
                high = mid - 1;
            }
        }
        // 可能会在数组左边越界, 可能数组中无指定查找元素,需要做判断
        if (high > 0 && a[high] == value) {
            return high;
        }
        return -1;
    }
  public static int bSearch2(int[] a, int n, int value) {
        int low = 0;
        int high = n - 1;

        while (low <= high) {
            int mid = high - ((high - low) >> 1);
            if (a[mid] < value) {
                high = mid - 1;
            } else if (a[mid] > value){
                low = mid + 1;
            } else {
                if (mid == n - 1 || a[mid + 1] != value) {
                    return mid;
                }else {
                    low = mid + 1;
                }
            }
        }
        return -1;
    }

查找第一个大于等于给定值的元素

 int erfenfirstlargeEqual(int arr,int key){
        int L = 0, R = arr.size() - 1; 
        int mid;
        // 与查找第一个等于的情况相似,挤压右边界,当右边界不满足时,返回左边界
        while( L <= R){
            mid = L + ((R - L) >> 1);
            if(arr[mid] >= key)
                R = mid - 1;
            else
                L = mid + 1;
        }
        // 判断是否越界
        if(L < arr.length)
            return L;
        return -1;
    }

查找最后一个小于等于给定值的元素

 int erfenfirstlargeEqual(int arr,int key){
        int L = 0, R = arr.size() - 1; 
        int mid;
        // 与查找最后一个情况相似,挤压左边界,当左边界不满足时,返回右边界
        while( L <= R){
            mid = L + ((R - L) >> 1);
            if(arr[mid] <= key)
                L = mid + 1;
            else
                R = mid - 1;
        }
        // 判断是否越界
        if(L < arr.length)
            return L;
        return -1;
    }

查找数组中第一个大于key的数字

    int erfenfirstLarge(vector<int> arr,int key){
        int L = 0,R = arr.size() - 1;
        int mid;
        // 挤压右边界, 返回左边界
        while(L <= R){
            mid = L + ((R - L) >> 1);
            if(arr[mid] > key)
                R = mid - 1;
            else
                L = mid + 1;
        }
        return L;
    }

查找数组中最后一个小于key的数字

int erfenlastSmall(vector<int> arr,int key){
        int L = 0, R = arr.size() - 1;
        int mid;
        while(L <= R){
            mid =  L + ((R - L) >> 1);
            if(arr[mid] < key)
                L = mid + 1;
            else
                R = mid - 1;
        }
        return R;
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值