33 搜尋旋轉陣列 python

2021-10-04 08:15:27 字數 4321 閱讀 5698

假設按照公升序排序的陣列在預先未知的某個點上進行了旋轉。( 例如,陣列[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

如果忽略題目對於時間複雜度的要求,這道題就沒有什麼可做性,直接使用線性遍歷即可。

class

solution

:def

search

(self, nums: list[

int]

, target:

int)

->

int:

if nums ==

:return-1

return nums.index(target)

if target in nums else

-1

既然時間複雜度要求為o

(log⁡n

)o(\log n)

o(logn

),那麼可以使用二分查詢。我一開始想著使用最基本的二分查詢來搜尋有序陣列,因為旋轉後的陣列並不是完全公升序排列,所以首先使用sorted()函式將其進行排列,然後在使用二分查詢。但是查閱資料發現sorted()的時間複雜度最壞為o(n

log⁡n)

o(n \log n)

o(nlogn)

,這樣演算法整體的時間複雜度就成了o(n

log⁡n)

o(n \log n)

o(nlogn)

,還是不符合題意,再想辦法。

class

solution

:def

search

(self, nums: list[

int]

, target:

int)

->

int:

if nums ==

:return-1

sortnums =

sorted

(nums)

l =0 r =

len(sortnums)-1

mid =

(l + r)//2

while l <= r:

mid =

(l + r)//2

if sortnums[mid]

== target:

return nums.index(sortnums[mid]

)elif sortnums[mid]

< target:

l = mid +

1else

: r = mid -

1return

-1

雖然旋轉後的陣列可能不是完全公升序排列,但是在旋轉點的兩周都是公升序排列的。例如[4,5,6,7,0,1,2]的旋轉點為0,4,5,6,7[0,1,2]都是完全公升序排列,我們可以在二分查詢的過程中利用這個性質。

如果nums[mid] != target,且nums[l: mid]不是完全公升序排列,那麼後半部分必定完全公升序排列。因此,先看nums[mid] < target <= nums[r]是否成立:

class

solution

:def

search

(self, nums: list[

int]

, target:

int)

->

int:

ifnot nums :

return-1

l =0 r =

len(nums)-1

while l <= r:

mid =

(l + r)//2

if nums[mid]

== target:

return mid

# 當前左半部分公升序

if nums[l]

<= nums[mid]

:# 如果位於左半部分,則在左半部分查詢

if nums[l]

<= target < nums[mid]

: r = mid -

1# 否則在右半部分查詢

else

: l = mid +

1else

:if nums[mid]

< target <= nums[r]

: l = mid +

1else

: r = mid -

1return

-1

另外,同樣是使用二分查詢,我們可以先使用二分查詢找到旋轉點的索引,然後在使用二分查詢找target。具體過程和基本的二分查詢區別不大,具體思路可見**。

from typing import list

class

solution

:# 尋找旋轉點的位置,即當前陣列的最小元素

deffindindex

(self, nums)

: l, r =

0,len

(nums)-1

# 如果頭小於尾表示陣列公升序,並無旋轉

if nums[l]

< nums[r]

:return

0# 二分查詢

while l <= r:

mid =

(l + r)//2

if nums[mid]

> nums[mid +1]

:return mid +

1else

:if nums[mid]

< nums[l]

: r = mid -

1else

: l = mid +

1def

search

(self, nums: list[

int]

, target:

int)

->

int:

# 考慮特殊的輸入情況

if nums ==

:return-1

iflen

(nums)==1

:return

0if nums[0]

== target else-1

index = self.findindex(nums)

if target == nums[index]

:return index

if index !=

0and target >= nums[0]

: n = nums[

:index]

elif index !=

0and target <= nums[-1

]:n = nums[index:

]else

: n = nums

l, r =

0, len

(n)-

1while l <= r:

mid =

(l + r)//2

if n[mid]

== target:

return nums.index(n[mid]

)elif n[mid]

< target:

l = mid +

1else

: r = mid -

1return

-1

搜尋旋轉陣列

假設有乙個排序的按未知的旋轉軸旋轉的陣列 比如,0 1 2 4 5 6 7 可能成為4 5 6 7 0 1 2 給定乙個目標值進行搜尋,如果在陣列中找到目標值返回陣列中的索引位置,否則返回 1。你可以假設陣列中不存在重複的元素。直接的方法是順序搜尋 更好的方法是二分搜尋 public class s...

旋轉陣列(python)

給定乙個陣列,將陣列中的元素向右移動 k 個位置,其中 k 是非負數。示例 1 輸入 1,2,3,4,5,6,7 和 k 3輸出 5,6,7,1,2,3,4 解釋 向右旋轉 1 步 7,1,2,3,4,5,6 向右旋轉 2 步 6,7,1,2,3,4,5 向右旋轉 3 步 5,6,7,1,2,3,4...

33 搜尋旋轉排序陣列 二分法 旋轉陣列

題目實際考察的是二分法。雖然旋轉後的陣列是部分有序的,但是由於每次迭代都必然有一部分 左部分或者右部分 是有序的,此時可以判斷當前數是否在有序的那部分,進而控制上下界。package com.walegarrett.interview author walegarrett date 2021 2 2...