二分查詢深度分析

2022-08-29 17:39:15 字數 1602 閱讀 8592

總結一句話就是:思路很簡單,細節是魔鬼,hhhh。

本部落格**幾個最常用的二分查詢場景:尋找乙個數、尋找左側邊界、尋找右側邊界。

public int binarysearch(int nums, int target) 

return -1;

}

答:

舉個例子推一下即可得知。因為當left=4,right=6時,此時mid=5;如果進入(nums[5] < target)分支時,left=6,如果是<,下次迴圈left=right=6不滿足leftleft <= right相當於兩端都閉區間 [left, right]中搜尋,left < right相當於左閉右開區間 [left, right)中搜尋。

答:比如說給你有序陣列 nums = [1,2,2,2,3],target = 2,此演算法返回的索引是 2,沒錯。但是如果我想得到 target 的左側邊界,即索引 1,或者我想得到 target 的右側邊界,即索引 3,這樣的話此演算法是無法處理的。

這樣的需求很常見。你也許會說,找到乙個 target,然後向左或向右線性搜尋不行嗎?可以,但是不好,因為這樣難以保證二分查詢對數級的複雜度了。

我們後續的演算法就來討論這兩種二分查詢的演算法。

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

}// target 比所有數都大

if (left == nums.length) return -1;

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

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

}

答:

關鍵在於對於 nums[mid] == target 這種情況的處理:

if (nums[mid] >= target)
int nums = ;

target = 6;

如果是left <= right,則會出現這種情況:

left=3,right=3,此時mid=3,當target在mid處命中即target=nums[mid],此時進入(nums[mid] >= target)分支,right = 3;所以這種情況它跳不出迴圈。

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

}if (left == 0) return -1;

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

}

與尋找左側邊界的二分查詢原理類似,故不在贅述。

高階:基本的二分搜尋的左右分支轉向代價不平衡的問題:

如[1,2,3],left=0,right=2,mid=1,進入左分支需要比較2次,進入右分支需要比較3次。

解決辦法:

1,斐波那契數(fibonacci)

2,變為2次比較

如有時間,下次闡述原理。

迭代二分查詢二分查詢

在寫這篇文章之前,已經寫過了幾篇關於改迭代二分查詢主題的文章,想要了解的朋友可以去翻一下之前的文章 bentley在他的著作 writing correct programs 中寫道,90 的計算機專家不能在2小時內寫出完整確正的二分搜尋演算法。難怪有人說,二分查詢道理單簡,甚至小學生都能明確。不過...

二分查詢實現與分析

在有序表或者陣列進行查詢元素的的時候,如果對其中的元素逐個進行比較查詢的話,當資料量很大時,假設陣列的元素個數為n個,那麼所對應的時間複雜度就是o n 對於o n 其實已經效率算是很快了。但作為貪心而又充滿智慧型的人類,我們總是能夠想到效率更快的演算法。天下武功,唯快不破。於是二分查詢就橫空出世。所...

1128 二分 二分查詢

時間限制 10000ms 單點時限 1000ms 記憶體限制 256mb 描述nettle最近在玩 艦 因此nettle收集了很多很多的船 這裡我們假設nettle氪了很多金,開了無數個船位 去除掉重複的船之後,還剩下n 1 n 1,000,000 種不同的船。每一艘船有乙個稀有值,任意兩艘船的稀有...