二分法細節

2022-09-26 10:06:35 字數 2871 閱讀 8139

int binarysearch(int nums, int target)  else if (nums[mid] < target)  else if (nums[mid] > target) 

}return ...;

}

分析二分查詢的乙個技巧是:不要出現 else,而是把所有情況用 else if 寫清楚,這樣可以清楚地展現所有細節。本文都會使用 else if,旨在講清楚,讀者理解後可自行簡化。

其中...標記的部分,就是可能出現細節問題的地方,當你見到乙個二分查詢的**時,首先注意這幾個地方。後文用例項分析這些地方能有什麼樣的變化。

另外宣告一下,計算 mid 時需要技巧防止溢位,建議寫成:mid = left + (right - left) / 2,本文暫時忽略這個問題。

這個場景是最簡單的,可能也是大家最熟悉的,即搜尋乙個數,如果存在,返回其索引,否則返回 -1。

左閉右閉的模板

int binarysearch(int nums, int target) 

return -1;

}

為什麼 while 迴圈的條件中是 <=,而不是 < ?

if(nums[mid] == target)

return mid;

//...

while(left < right)

return nums[left] == target ? left : -1; //注意 如果是插入位置 需要先判段left是否越界

為什麼 left = mid + 1,right = mid - 1?我看有的**是 right = mid 或者 left = mid,沒有這些加加減減,到底怎麼回事,怎麼判斷?

此演算法有什麼缺陷?

直接看**,其中的標記是需要注意的細節: //正常二分法左閉右開的模板

int left_bound(int nums, int target)  else if (nums[mid] < target)  else if (nums[mid] > target) 

}return left;

}

為什麼 while(left < right) 而不是 <= ?

為什麼沒有返回 -1 的操作?如果 nums 中不存在 target 這個值,怎麼辦?

while (left < right) 

// target 比所有數都大

if (left == nums.length) return -1; //[1,2,2,4]搜尋8返回left 4,越界

// 類似之前演算法的處理方式

return nums[left] == target ? left : -1;

為什麼 left = mid + 1,right = mid ?和之前的演算法不一樣?

為什麼該演算法能夠搜尋左側邊界?

if (nums[mid] == target)

right = mid;

為什麼返回 left 而不是 right?

尋找右側邊界和尋找左側邊界的**差不多,只有兩處不同,已標註:

int right_bound(int nums, int target)  else if (nums[mid] < target)  else if (nums[mid] > target) 

}return left - 1; // 注意

為什麼這個演算法能夠找到右側邊界?

if (nums[mid] == target) 

if (left == 0) return -1;  //這個例子搜尋0 就是返回left 0

return nums[left-1] == target ? (left-1) : -1;

先來梳理一下這些細節差異的因果邏輯:

第乙個,最基本的二分查詢演算法:

因為我們初始化 right = nums.length - 1所以決定了我們的「搜尋區間」是 [left, right]所以決定了 while (left <= right)同時也決定了 left = mid+1 和 right = mid-1

因為我們只需找到乙個 target 的索引即可所以當 nums[mid] == target 時可以立即返回

第二個,尋找左側邊界的二分查詢:

因為我們初始化 right = nums.length所以決定了我們的「搜尋區間」是 [left, right)所以決定了 while (left < right)同時也決定了 left = mid+1 和 right = mid

因為我們需找到 target 的最左側索引所以當 nums[mid] == target 時不要立即返回而要收緊右側邊界以鎖定左側邊界

第三個,尋找右側邊界的二分查詢:

因為我們初始化 right = nums.length所以決定了我們的「搜尋區間」是 [left, right)所以決定了 while (left < right)同時也決定了 left = mid+1 和 right = mid

因為我們需找到 target 的最右側索引所以當 nums[mid] == target 時不要立即返回而要收緊左側邊界以鎖定右側邊界

又因為收緊左側邊界時必須 left = mid + 1所以最後無論返回 left 還是 right,必須減一

**自詳解二分查詢演算法 - murphy_gb - (cnblogs.com)

二分法細節總結

二分法的思想很容易理解,但是細節處理卻是乙個難點。很容易就容易出錯。這裡總結一下這些細節。區間為 left,right 情況 右邊指標取不到元素 初始化 left 0 right arr.length 迴圈條件 left right 注意事項 left 的更新是取到值的情況 right的更新是不取到...

C 二分法查詢,遞迴二分法

用二分法來求需要查詢的值.includeusing namespace std 查詢key元素是否存在 int findkey const int buf 100 const int ilen,const int key else right left mid 1 查詢失敗 return 1 查詢k...

python二分法查詢 Python 二分法查詢

二分法查詢主要的作用就是查詢元素 lst 1,3,5,7,12,36,68,79 資料集 百萬級資料 num int input 請輸入你要查詢的元素資訊 for el in lst if num el print 存在 break else print 不存在 len lst 0 1 2 3 4 ...