二分查找之第一個大於小於等於 target 的值

歡迎瀏覽作者的GitHub

二分查找概述

條件:只能對已經排序好的列表進行查找。
需求:對搜索時間要求爲O(logn)一般都是二分查找。
概述:通過對經典二分查找的修改,達到日常查找的各種需求,
如1、查找某個值 target,2、查找第一個大於 target 的值,3、查找第一個小於 target 的值,4、查找第一個大於等於 target的值,5、查找第一個 小於等於 target 的值。
對於經典的算法,只要進行簡單的修改,即可滿足多種情況
條件:left <= right
結束時:left 指向第一個不滿足 if 條件中的值,
如if(array[mid] < target):就是第一個大於等於target的值
如if(array[mid] <= target):就是第一個大於target的值

1、查找某個值 target

注意:如果不存在這個值,結束時:left > right,且 left 的座標爲第一個大於 target 的值。

public int binarySearchOne() {
   int[] array = {0,1,2,3,4,5,6};
   int target = 3;
	int left = 0, right = array.length-1;
	while(left <= right) {
		int mid = (left+right)/2;
		if(array[mid] == target)
			return mid;
		if(array[mid] < target)
            left = mid + 1;
		else
		   right = mid - 1;
	}
	return -1;
}

2、查找第一個大於(大於等於) target 的值

注意:結束時:left > right,如果 target 即爲最大值,則會產生數組越界,需要對 left 進行判斷,不能直接返回。
修改:大於等於也很好修改,只需要將 if 裏的判斷條件改爲 if(array[mid] < target) 即可。

public int binarySearchOne() {
   int[] array = {0,1,2,3,4,5,6};
   int target = 3;
	int left = 0, right = array.length-1;
	while(left <= right) {
    //只修改了判斷的條件,相當於將小於等於歸爲一類。
		if(array[mid] <= target)
            left = mid + 1;
		else
		   right = mid - 1;
	}
	return left;
}

3、查找第一個小於(小於等於) target 的值

注意:結束時:left > right,如果 target 即爲最小值,則會產生數組越界,需要對 right 進行判斷,不能直接返回。
修改:小於等於也很好修改,只需要將 if 裏的判斷條件改爲 if(array[mid] > target) 即可。

public int binarySearchOne() {
   int[] array = {0,1,2,3,4,5,6};
   int target = 3;
	int left = 0, right = array.length-1;
	while(left <= right) {
    //只修改了判斷的條件,相當於將大於等於歸爲一類。
		if(array[mid] >=  target)
            right = mid - 1;
		else
		     left = mid + 1;
	}
	return right;
}

4、另一種寫法,幫助你理解二分查找

算法:查找第一個大於 target 值的座標。
注意:1、修改了循環條件:left < right,所以結束是 left == right。2、當遇到大於 target 值時,right = mid,保留當前可能的座標。
好處:不會產生數組越界的下標,如果 target 即爲最大值,則 left == right == array.length-1。否則一定會指向第一個大於 target 的座標。

public int binarySearchTwo(int[] array, int left, int right,int target){
        while(left < right){ //修改了循環判斷
            int mid = (left+right)/2;
            if(array[mid] <= target) //大於要保留
                left = mid + 1;
            else
                right = mid;
        }
        if(array[left] >= target) //最後結束時有left==right,如果一定存在,則不需要以下語句,直接返回即可。
            return left;
        return -1; //如果target即是最大值,則返回-1;

5、一個優秀的用二分查找尋找邊界的方法

例題:查找左右邊界,計算目標值的數量,使用了兩次查找第一個最大值。

public int search(int[] nums, int target) {
    return binarySearch(nums, target + 0.5) - binarySearch(nums, target - 0.5);
}

private int binarySearch(int[] nums, double target) {
    int left = 0, right = nums.length - 1;
    while (left <= right) {
        int mid = (right + left) /2;
        if (nums[mid] < target) 
            left = mid + 1;
       else
            right = mid - 1;
        }
    return left;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章