來玩二分查找[NO.1]

來玩二分查找

二分查找是典型的看起來很普通,當時細節卻很複雜的算法,可以理解爲:思路很簡單,細節是魔鬼,各種邊界情況複雜,如果想不通不妨在紙上模擬計算。

本篇博客就開始來探尋一下二分查找,常用的幾個二分查找,尋找一個數,尋找左側邊界,尋找右側邊界等情況,循環結束條件是什麼,索引到底是該加一還是減一等情況,分析細節及細節的差異。

先來一個簡單的二分查找代碼

public static void getTwoNum4(int[] arr, int num) {
		int left = 0;
		// 數組索引從0開始,長度從1開始
		int right = arr.length - 1;

		// 爲什麼要小於等於,必須以left或right爲標的,大於覆蓋一邊,否則如果是相等,則相等的索引就會被漏掉
		// 這裏可以帶入(3<=2) 只有當left+1>right循環終止,且區間爲空
		while (left <= right) {
			int index = (left + right) / 2;
			if (num == arr[index]) {
				System.out.println("找到符合要求的數:" + arr[index]);
				break;
			} else if (arr[index] > num) {
				// 傳統做法right--相當於從右向左完整遍歷,當索引值大於目標數,則右側索引減一
				// right--;
				// 根據索引值大於目標數,從索引處減一,排除索引右側大於目標數,複雜度更小
				right = index - 1;
			} else if (arr[index] < num) {
				// 傳統做法left++相當於從左向右完整遍歷,當索引值小於目標數,則左側索引加一
				// left++;
				// 根據索引值小於目標數,從索引處加一,排除索引左側小於目標數,複雜度更小
				left = index + 1;
			}
		}
	}

細節問題

  • right索引爲什麼是 arr.length-1?
    答:數組索引下標從0開始,數組的長度從1開始,右側數組最大索引是長度-1,否則會越界

  • 爲什麼while的循環條件是<=而不是<

在這裏插入圖片描述
從圖上可以看出來,必須以left或right爲標的,大於覆蓋一邊,否則如果是相等,則相等的索引就會被漏掉,如上圖第一列數組,如果循環條件是while(left<rigth)帶入(3,3),循環結束則會漏掉索引3,如上圖第二列數組,如果循環條件是while(left<=rigth)帶入(3,2),沒有數字比3大比2小,則while循環完整結束。

  • 循環判斷條件arr[index]>num爲什麼right=arr[index]-1
    答:傳統做法是當索引值大於目標值,右側索引減減,相當於從右向左完整遍歷查找,二分查找是當(left+right)/2,獲取數組中間索引值,比較如果大於目標數值,則代表目標數值在於數組的左側,排除索引右側大於目標數,所以right索引爲index-1;同理如果數組中間索引值,比較小於目標數值,則代表目標數值在於數組右側,排除索引左側小於目標數,所以left的索引爲index+1,查找複雜度更小。

左側邊界和右側邊界二分查找後續更新!

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