假設按照公升序排序的陣列在預先未知的某個點上進行了旋轉。( 例如,陣列 [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
找斷點,斷點左右分別是有序的,然後就可以分別對左右兩段用二分查詢法(logn複雜度)了。
class
solution
:def
search
(self, nums: list[
int]
, target:
int)
->
int:
# 找斷點比較有意思:我們通過l 和 r 求 mid。
# 最右邊的r永遠是在遞增序列中,
# 如果num[mid] < num[r],說明我們這個mid與r在同乙個遞增序列,
# 我們減少r,令r=mid,縮小範圍去查詢斷點。
# 如果num[mid] > num[r],說明mid與r在不同的遞增序列,增大l,令l= mid+1, 不斷逼近斷點。
# 其實也可以看做不用遞迴方法的二分查詢
l =0 r =
len(nums)-1
while l < r:
mid =
(l + r)//2
if nums[mid]
> nums[r]
: l = mid +
1else
: r = mid
# 找到斷點
pol = l
# 然後在左段二分查詢
ans = self.binary_search_2(nums[
:pol]
, target)
if ans ==-1
:# 如果沒有找到,則一定在右段
ans = self.binary_search_2(nums[pol:
], target)
if ans !=-1
: ans +=
len(nums[
:pol]
)return ans
# 以下是二分查詢法的兩種實現,二分查詢需要陣列為有序排列
# 遞迴
defbinary_search_1
(self, nums, left, right, target)
:if left < right:
return-1
mid =
(lef + right)//2
if nums[mid]
== target:
return mid
elif target < nums[mid]
: right = mid -
1else
: left = mid +
1return binary_search_1(self, nums, left, right, target)
# 迴圈
defbinary_search_2
(self, nums, target)
: index =-1
l =0 r =
len(nums)-1
# 雙指標移動一般用while
while l <= r:
mid =
(l+r)//2
if nums[mid]
< target:
l = mid +
1elif nums[mid]
> target:
r = mid -
1else
: index = mid
break
return index
LeetCode 33 搜尋旋轉排序陣列
假設按照公升序排序的陣列在預先未知的某個點上進行了旋轉。例如,陣列 0,1,2,4,5,6,7 可能變為 4,5,6,7,0,1,2 搜尋乙個給定的目標值,如果陣列中存在這個目標值,則返回它的索引,否則返回 1。你可以假設陣列中不存在重複的元素。你的演算法時間複雜度必須是 o log n 級別。示例...
leetcode 33 搜尋旋轉排序陣列
leetcode 33.搜尋旋轉排序陣列 假設按照公升序排序的陣列在預先未知的某個點上進行了旋轉。例如,陣列 0,1,2,4,5,6,7 可能變為 4,5,6,7,0,1,2 搜尋乙個給定的目標值,如果陣列中存在這個目標值,則返回它的索引,否則返回 1 你可以假設陣列中不存在重複的元素。你的演算法時...
leetcode33 搜尋旋轉排序陣列
leetcode33 搜尋旋轉排序陣列原題鏈結 題意簡述假設按照公升序排序的陣列在預先未知的某個點上進行了旋轉。例如,陣列 0,1,2,4,5,6,7 可能變為 4,5,6,7,0,1,2 搜尋乙個給定的目標值,如果陣列中存在這個目標值,則返回它的索引,否則返回 1 你可以假設陣列中不存在重複的元素...