來玩二分查找[NO.2]--左側(右側)邊界的二分搜索

什麼是左側(右側)邊界二分查找

上一篇博客,細訴了二分查找的細節和實現邏輯,當時存在侷限性,比如有一個數組int[] arr={1,2,2,2,3,5,7},目標num=2,返回索引是3,假如需要返回最左側索引(1)或最右側的索引(3),這樣的話普通二分查找是無法實現的

來一個左側邊界二分查找:

public static int getTwoNum5(int[] arr, int num) {
		int left = 0;
		int right = arr.length;
		// while(left < right) 終止的條件是 left == right,此時搜索區間 [left, left)
		// 爲空,所以可以正確終止
		while (left < right) {
			int index = (left + right) / 2;
			System.out.println("當前索引位置:" + index + "索引值爲:" + arr[index]);
			if (num == arr[index]) {
				// 當查詢索引index查詢到標的值,不立即返回而是縮小right邊界[left,index]繼續往左側邊界查找
				right = index;
			} else if (arr[index] > num) {
				// 初始二分索引值比標的num值大,查詢範圍[0,index]
				right = index;
			} else if (arr[index] < num) {
				// 初始二分索引值比標的num小,查詢範圍[index+1,right)
				left = index + 1;
			}
		}
		return arr[left] == num ? left : -1;
	}

細節問題:

  • 爲什麼right=arr.length而不是arr.length-1
    答:因爲搜索區間是左閉右開的,當arr[index]=num或者arr[index]>num時,循環範圍都是[left,index),這樣不斷搜索區間靠左查詢。

  • 爲什麼while的循環條件是<而不是<=
    答:當查詢最左側或者最右側邊界成立時即arr[index]=num,右側邊界會賦值爲right=index,如果循環結束條件leth<=right,最左側情況(0,0)或最右側情況(arr.lenght-1,arr.lenght-1)出現死循環無法改出。

  • 爲什麼right=index;left=index+1
    答:是爲了切割二分查詢後左右兩側邊界,當初次二分索引查詢值比標的num大時,查詢範圍切割爲[left,index),當比標的num小時,查詢範圍切割爲[index+1,right)。

  • 爲什麼numarr[index]時right=index
    答:當查詢索引index查詢到標的值num時,不立即返回而是縮小right邊界[left,index]繼續往左側邊界查找,可以一直查到最左側,如果出現[index+1,right],當num
    arr[index],則查詢直接返回

  • 如果是右側邊界的二分搜索
    答:只需要在num==arr[index]成立時,不立即返回而是縮小left邊界,賦值left=index+1繼續向右側查找[index+1,right].

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章