二分查詢的思想和套路已經了然於心了,但是還是有些問題解決不了?這個時候就可能需要多見一些特殊的用例了。這一次再來一種二分查詢的特例。
峰值元素是指其值大於左右相鄰值的元素。給定乙個輸入陣列 nums,其中 nums[i] ≠ nums[i+1],找到峰值元素並返回其索引。
陣列可能包含多個峰值,在這種情況下,返回任何乙個峰值所在位置即可。
你可以假設 num
s[−1
]=nu
ms[n
+1]=
−∞
nums[-1] = nums[n+1] = -∞
nums[−
1]=n
ums[
n+1]
=−∞。
示例 1:
輸入:nums = [1,2,3,1]
輸出: 2
解釋: 3 是峰值元素,你的函式應該返回其索引 2。
示例 2:輸入: nums = [1,2,1,3,5,6,4]
輸出: 1 或 5
解釋: 你的函式可以返回索引 1,其峰值元素為 2;
或者返回索引 5, 其峰值元素為 6。
這個問題也是查詢中的乙個典型,雖然看起來不是那麼難,但是告訴你這是乙個二分查詢的題目,想出o(l
gn
)o(lgn)
o(lgn)
複雜度的解也是不那麼容易。
題目中提到後乙個元素不會和前乙個元素相同,這一點就保證了峰值實際上是嚴格的峰值。此外還提到num
s[−1
]=nu
ms[n
+1]=
−∞
nums[-1] = nums[n+1] = -∞
nums[−
1]=n
ums[
n+1]
=−∞,這一條就假設了峰值一定存在。陣列中的最大值一定是峰值。所以問題一定是有解的。而且只需要返回乙個解,肯定不需要遍歷了。
首先注意到這個問題中陣列都不是有序或者區域性有序的,如果要使用二分查詢,這個時候需要聯想二分查詢的特性,如何去劃分子問題。
肯定要找到中間元素,但是中間元素的情況如何決定解的位置。找峰值,仍然以上坡和下坡為例。如果中間元素處於上坡的區間,顯然峰值出現在右邊。如果中間元素處於下坡的區間,則峰值出現在左邊。接下來就是判斷中間元素到底在上坡還是下坡了。那就比較它和自己後面的元素,到底哪個更大。如果比下乙個元素大,就是在下坡,反之則是上坡。(不會出現相等的情況)
找到了如何劃分問題。還需要注意的一點就是,如果自己比下乙個元素大,說明在下坡,此時可能自己就是坡頂元素,這個時候二分法的結束位置就需要包括自己的當前位置。
c++**
int
findpeakelement
(vector<
int>
& nums)
else
}return start;
}
通常的二分查詢,需要對比的是中間元素和兩端元素的關係,但是實際上也可以對比中間元素和周圍元素的關係來查詢。因為計算機中的除法都是向下取整,所以當sta
rt≠e
nd
start \neq end
start
=en
d時,mid
+1
mid +1
mid+
1一定在區間內,而mid
−1
mid - 1
mid−
1則不一定在。這一點也是需要注意的。
二分查詢時間複雜度的計算
時間複雜度無非就是while迴圈的次數!總共有n個元素,漸漸跟下去就是n,n 2,n 4,n 2 k,其中k就是迴圈的次數 由於你n 2 k取整後 1 即令n 2 k 1 可得k log2n,是以2為底,n的對數 所以時間複雜度可以表示o o logn 二分查詢的時間複雜度是o log n 最壞情況...
二分查詢時間複雜度的計算
時間複雜度無非就是while迴圈的次數!總共有n個元素,漸漸跟下去就是n,n 2,n 4,n 2 k,其中k就是迴圈的次數 由於你n 2 k取整後 1 即令n 2 k 1 可得k log2n,是以2為底,n的對數 所以時間複雜度可以表示o o logn 二分查詢的時間複雜度是o log n 最壞情況...
順序查詢和二分查詢法複雜度的差異
1.問題 寫出兩種檢索演算法 在乙個排好序的陣列t 1 n 中查詢x,如果x在t中,輸出x在 t的下標j 如果x不在t中,輸出j 0。2.分析 兩種檢索演算法,我們選擇1.順序查詢法。2.二分查詢法。3.偽 順序查詢法 for int i 0 i n i 二分查詢法 int top 0,end n ...