假設按照公升序排序的陣列在預先未知的某個點上進行了旋轉。( 例如,陣列[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
(logn
)o(\log n)
o(logn
),那麼可以使用二分查詢。我一開始想著使用最基本的二分查詢來搜尋有序陣列,因為旋轉後的陣列並不是完全公升序排列,所以首先使用sorted()函式將其進行排列,然後在使用二分查詢。但是查閱資料發現sorted()的時間複雜度最壞為o(n
logn)
o(n \log n)
o(nlogn)
,這樣演算法整體的時間複雜度就成了o(n
logn)
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...