leetcode練習之陣列33 搜尋旋轉排序陣列

2021-10-03 19:33:04 字數 1927 閱讀 1469

假設按照公升序排序的陣列在預先未知的某個點上進行了旋轉。

( 例如,陣列 [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 級別。示例...