**自:leetcode題解區-一文解決 4 道「搜尋旋轉排序陣列」題
可以分為 3 類:
題目要求時間複雜度$o(logn)$,顯然應該使用二分查詢。二分查詢的過程就是不斷收縮左右邊界,而怎麼縮小區間是關鍵。
如果陣列「未旋轉」,在陣列中查詢乙個特定元素target
的過程為:
但是這道題,由於陣列「被旋轉」,所以左側或者右側區間不一定是連續的。在這種情況下,如何判斷target
位於哪個區間?
首先,乙個重要的結論:將區間分均分,必然有一半有序,一半無序。問題是如何找到有序的那一半?
根據旋轉陣列的特性,當元素不重複時,如果nums[i] <= nums[j]
,說明區間[i,j]
是「連續遞增」的。
因此,在旋轉排序陣列中查詢乙個特定元素時:
否則,說明右側區間[mid,right]
「連續遞增」。此時:
注意:區間收縮時不包含mid
,也就是說,實際收縮後的區間是[left,mid)
或者(mid,right]
可以很容易地寫出**:
int search(vector& nums, int target)
else
}return -1;
}
這道題是 33 題的公升級版,元素可以重複。當nums[left] == nums[mid]
時,無法判斷target
位於左側還是右側,此時無法縮小區間,退化為順序查詢。
例如 [1, 3, 1, 1, 1]中查詢3,按原來的**就會出錯。
順序查詢的一種方法是直接遍歷[left,right]
每一項:
if nums[left] == nums[mid]
}
另一種方法是令left++
,去掉乙個干擾項,本質上還是順序查詢:
if nums[left] == nums[mid]
其實這道題沒有低於o(n)的演算法,所以直接遍歷一遍即可。
如果陣列沒有翻轉,即nums[left] <= nums[right]
,則nums[left]
就是最小值,直接返回。
如果陣列翻轉,需要找到陣列中第二部分的第乙個元素:
下面討論陣列翻轉的情況下,如何收縮區間以找到這個元素:
}這道題是 153 題的公升級版,元素可以重複。和 81 題一樣,當nums[left] == nums[mid]
時,退化為順序查詢。
81 題提供了兩種方法:
154 題只能使用第一種方法。因為如果left
是最小元素,那麼left++
就把正確結果給跳過了。
演算法題 搜尋旋轉排序陣列
假設按照公升序排序的陣列在預先未知的某個點上進行了旋轉。例如,陣列 0,1,2,4,5,6,7 可能變為 4,5,6,7,0,1,2 搜尋乙個給定的目標值,如果陣列中存在這個目標值,則返回它的索引,否則返回 1。你可以假設陣列中不存在重複的元素。你的演算法時間複雜度必須是 o log n 級別。1 ...
每日一題 搜尋旋轉排序陣列
題目描述 假設按照公升序排序的陣列在預先未知的某個點上進行了旋轉。例如,陣列 0,1,2,4,5,6,7 可能變為 4,5,6,7,0,1,2 搜尋乙個給定的目標值,如果陣列中存在這個目標值,則返回它的索引,否則返回 1 你可以假設陣列中不存在重複的元素。你的演算法時間複雜度必須是 o log n ...
lintcode刷題 搜尋旋轉排序陣列
原題如下 搜尋旋轉排序陣列 假設有乙個排序的 按未知的旋轉軸旋轉的 陣列 比如,0 1 2 4 5 6 7 可能成為 4 5 6 7 0 1 2 給定乙個目標值進行搜尋,如果在陣列中找到目標值返回陣列中的索引位置,否則返回 1。你可以假設陣列中不存在重複的元素。您在真實的面試中是否遇到過這個題?ye...