前言
所謂旋轉排序陣列,就是指按照公升序排序的陣列在預先未知的某個點上進行了旋轉(例如,陣列[0,1,2,4,5,6,7]
可能變為[4,5,6,7,0,1,2]
)。而leetcode上與此相關的的題共有三道,下面就具體來分析一下這三題。
搜尋旋轉排序陣列(leetcode 33題)
搜尋乙個給定的目標值,如果陣列中存在這個目標值,則返回它的索引,否則返回 -1 。你可以假設陣列中不存在重複的元素。分析你的演算法時間複雜度必須是 o(log n) 級別。
示例 1:
輸入: nums = [4,5,6,7,0,1,2], target = 0
輸出: 4
示例 2:
輸入: nums = [4,5,6,7,0,1,2], target = 3
輸出: -1
從題目要求時間複雜度為o(logn),則可知最終必須使用二分法。然後再具體分析旋轉陣列的特徵,假設在下標i
處進行了旋轉,旋轉後的序列為i ~ n-1, 0 ~ i-1
,由於陣列本身是公升序排列的,所以仔細分析mid
中間結點的位置,便可以找到這題的突破口,假設mid
處於i ~ n-1
區間內,那麼i ~ mid
段就是有序的,相對地,mid ~ i-1
就是無序的。當mid
結點處於0 ~ i-1
區間時,易知mid ~ i-1
段是有序的,相對地,i ~ mid
就是無序的。可以發現,無論mid在哪個位置,總能得到乙個有序段,最終我們也就是利用有序段,來每次排除一半的資料。
為了分析有序段,再看題目,因為陣列為公升序,因此我們每次只需要和最右邊的結點進行比較即可。若nums[mid] < nums[right]
,則mid ~ right
段為有序,若nums[mid] > nums[right]
,由於陣列整體為公升序,原陣列中左邊的資料一定是小於右邊的,因此在mid ~ right
存在乙個旋轉點,即該段是無序的,再由上文分析可知,無論mid
處於哪一段,總存在有序區間,因此此時i ~ mid
段是有序的。
當我們得到有序段後,我們便可以根據target
是否存在於有序段來取捨一半的資料,最終的**如下:
public
intsearch
(int
nums,
int target)
if(nums[mid]
> nums[right]
)else
}else
else}}
return-1
;}
複雜度分析
尋找旋轉排序陣列中的最小值(leetcode153題)
分析 本題的條件和上一題相同,取別是上題要求找到乙個目標值,而本題則要求找到最小值。再次回想之前的分析,假設在下標i
處進行了旋轉,旋轉後的序列為i ~ n-1, 0 ~ i-1
,對於mid
結點而言,由之前的分析可知,可以由mid
結點與最右邊的結點的值的大小關係,判斷出有序區間處於mid
之前還是之後。再次分析有序區間,假設i ~ mid
段為有序,那麼陣列一定是在mid ~ i-1
段的某個位置進行了旋轉,相應地,最小值也存在於這個區間,即存在於無序段。當mid ~ i-1
為有序時,則根據上文的分析,最小值也一定存在於存在旋轉結點的區間,即無序段。
經過上文的分析,可知最小值(也就是旋轉結點)一定存在於無序段,因此**也很容易得出,如下:
public
intfindmin
(int
nums)
else
}return nums[left]
;}
複雜度分析
存在重複值的陣列
以上兩題均是不考慮陣列有重複元素的情況,而leetcode81題和154題,則正是以上兩題存在重複元素的改變。當存在重複元素時,我們在判斷mid
與right
結點的大小也將多了一種可能相等的情況,那麼怎麼考慮相等呢?其實我們只要每次在相等情況判斷時,都只將right--
即可,因為不管是尋找目標值target
,還是尋找陣列最小值,因為mid
與right
相等,所以每次去掉最右結點,再對剩下部分之前的判斷,即可得到最終的結果。但是,在有重複值的情況下,演算法的時間複雜度也有了改變,在最好的情況下(陣列中不存在重複元素),仍未o(logn)。但在最壞的情況下(陣列元素全部相等),由於每次只能將陣列大小縮減1,因此將退化為o(n)。
Leetcode 搜尋旋轉排序陣列
假設按照公升序排序的陣列在預先未知的某個點上進行了旋轉。例如,陣列 0,1,2,4,5,6,7 可能變為 4,5,6,7,0,1,2 搜尋乙個給定的目標值,如果陣列中存在這個目標值,則返回它的索引,否則返回 1 你可以假設陣列中不存在重複的元素。你的演算法時間複雜度必須是 o log n 級別。示例...
leetcode 搜尋旋轉排序陣列
假設按照公升序排序的陣列在預先未知的某個點上進行了旋轉。例如,陣列 0,1,2,4,5,6,7 可能變為 4,5,6,7,0,1,2 搜尋乙個給定的目標值,如果陣列中存在這個目標值,則返回它的索引,否則返回 1 你可以假設陣列中不存在重複的元素。你的演算法時間複雜度必須是 o log n 級別。示例...
LeetCode 搜尋旋轉排序陣列
原題鏈結 33.搜尋旋轉排序陣列 給你乙個整數陣列 nums 和乙個整數 target 該整數陣列原本是按公升序排列,但輸入時在預先未知的某個點上進行了旋轉。例如,陣列 0,1,2,4,5,6,7 可能變為 4,5,6,7,0,1,2 請你在陣列中搜尋 target 如果陣列中存在這個目標值,則返回...