假設按照公升序排序的陣列在預先未知的某個點上進行了旋轉。
( 例如,陣列 [0,1,2,4,5,6,7] 可能變為 [4,5,6,7,0,1,2] )。
搜尋乙個給定的目標值,如果陣列中存在這個目標值,則返回它的索引,否則返回 -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(log n) 級別,所以很快我們就能想到用二分法進行搜尋。只是二分法需要在有序的陣列中操作,但是我們這裡旋轉後的排序陣列是分段有序。
分步將旋轉陣列恢復,然後二分法
首先這種分步思維有利於我們把問題拆解。有些像是想成為救火員的故事中的數學家的思維。儘管令人啼笑皆非,但是有規律可循,如果遇到火,就滅火;如果沒有火,那就先點火,再滅火。
其實這裡有個小提示,二分法需要在有序陣列中使用,且每次劃分是以一半進行。那麼我們可以一半一半的判斷是否有序。這也就引導我們到了乙個更完備的演算法。如下所示。
直接二分法
如果mid的值大於等於start的值,那麼從start到mid這部分為有序陣列
如果target介於start和mid的值之間,則二分法在前半部分查詢
反之,如果mid的值小於start的值,那麼從mid到end這部分為有序陣列
如果target介於mid和end的值之間,則二分法在後半部分查詢
執行用時:8 ms
記憶體消耗:15.2 mb
class
solution
$start=0
;$end
=count
($nums)-
1;while
($start
<=
$end
)//前半部分有序if(
$nums
[$start
]<=
$nums
[$mid])
else
}else
else}}
return-1
;}}
執行用時 :0 ms
記憶體消耗 :2.6 mb
func
search
(nums [
]int
, target int
)int
start,end :=0,
len(nums)-1
for start<=end
//前半部分有序
if(nums[start]
<=nums[mid]
)else
}else
else}}
return-1
}
發現耗時和記憶體占用此消彼長,由於這一版的耗時是0ms,所以我不禁想減少記憶體消耗。發現可以在while迴圈外先宣告mid,在裡面給mid再修改賦值。這樣記憶體占用就打敗100%的go提交記錄了。當然耗時增加了。
start,mid,end :=0,
0,len(nums)
-1
直接二分法的最好時間複雜度o(1),最壞時間複雜度o(log n),平均時間複雜度o(log n)。
直接二分法的最好空間複雜度o(1),最壞空間複雜度o(1),平均空間複雜度o(1)。
don』t you quit.
leetcode演算法練習 33 搜尋旋轉排序陣列
所有題目源 git位址 題目假設按照公升序排序的陣列在預先未知的某個點上進行了旋轉。例如,陣列 0,1,2,4,5,6,7 可能變為 4,5,6,7,0,1,2 搜尋乙個給定的目標值,如果陣列中存在這個目標值,則返回它的索引,否則返回 1 你可以假設陣列中不存在重複的元素。你的演算法時間複雜度必須是...
3 3 演算法練習
時間限制 1.0s 記憶體限制 512.0mb 輸入乙個正整數n,輸出n 的值。其中n 12 3 n。n 可能很大,而計算機能表示的整數範圍有限,需要使用高精度計算的方法。使用乙個陣列a來表示乙個大整數a,a 0 表示a的個位,a 1 表示a的十位,依次類推。將a乘以乙個整數k變為將陣列a的每乙個元...
leetcode33 搜尋旋轉排列陣列
假設按照公升序排序的陣列在預先未知的某個點上進行了旋轉。例如,陣列 0,1,2,4,5,6,7 可能變為 4,5,6,7,0,1,2 搜尋乙個給定的目標值,如果陣列中存在這個目標值,則返回它的索引,否則返回 1 你可以假設陣列中不存在重複的元素。你的演算法時間複雜度必須是 o log n 級別。示例...