【每日演算法】二分查詢法II
阿新 • • 發佈:2021-08-05
目錄
模板
left,right=1,n
while left<=right:
mid=left+(right-left)//2
if 條件:
right=mid+1
else:
left=mid-1
- 定義左右邊界
- 左邊界小於右邊屆時進入迴圈體
- 取中間數,使用
left+(right-left)//2
是防止越界的問題 - 根據業務條件不斷的向中間移動left和right
例題
33.搜尋旋轉排序陣列
描述
整數陣列 nums 按升序排列,陣列中的值 互不相同 。 在傳遞給函式之前,nums 在預先未知的某個下標 k(0 <= k < nums.length)上進行了 旋轉,使陣列變為 [nums[k], nums[k+1], ..., nums[n-1], nums[0], nums[1], ..., nums[k-1]](下標 從 0 開始 計數)。例如, [0,1,2,4,5,6,7] 在下標 3 處經旋轉後可能變為[4,5,6,7,0,1,2] 。 給你 旋轉後 的陣列 nums 和一個整數 target ,如果 nums 中存在這個目標值 target ,則返回它的下標,否則返回-1。
示例1
輸入:nums = [4,5,6,7,0,1,2], target = 0
輸出:4
示例2
輸入:nums = [4,5,6,7,0,1,2], target = 3
輸出:-1
示例3
輸入:nums = [1], target = 0
輸出:-1
提示
1 <= nums.length <= 5000
-10^4 <= nums[i] <= 10^4
nums 中的每個值都 獨一無二
題目資料保證 nums 在預先未知的某個下標上進行了旋轉
-10^4 <= target <= 10^4
思路
直接先套用模板
n=len(nums) left,right=0,n-1 while left<=right: mid=left+(right-left)//2 if 條件: right=mid-1 else: left=mid+1
然後補充條件
首先 如果 nums[mid]=target 那麼就可以直接返回
if nums[mid]==target: return mid
再次nums[mid]
肯定落在nums陣列的前半段或後半段,有題目可知,nums是有兩個升序的序列組成,如果nums[left]<=nums[mid]
那nums[mid]
落在前半段的升序列裡,否則就落在了後半段的升序列裡。
如果落在了前段的升序裡,則用nums[l]、nums[mid]
與target
進行比較
if nums[l]<=target<nums[mid]:
r=mid-1
else:
l=mid+1
否則
if nums[mid]<target<=nums[r]:
r=mid-1
else:
l=mid+1
程式碼
class Solution(object):
def search(self, nums, target):
#在取中間數的時候,分3種情況
# 1 nums[mid]==target 就直接返回mid,找到結果了
# 2 nums[mid]>=nums[l] 既落在左邊的序列裡
# 3 否則 就落在右邊的序列裡
n=len(nums)
l,r=0,n-1
while l<=r:
mid=l+(r-l)//2
if nums[mid]==target:
return mid
if nums[l]<=nums[mid]:#說明左邊是有序的
if nums[l]<=target<nums[mid]:
r=mid-1
else:
l=mid+1
else:#否則右邊有序
if nums[mid]<target<=nums[r]:
r=mid-1
else:
l=mid+1
return -1
153.尋找旋轉排序陣列中的最小值
描述
已知一個長度為 n 的陣列,預先按照升序排列,經由 1 到 n 次 旋轉 後,得到輸入陣列。例如,原陣列 nums = [0,1,2,4,5,6,7] 在變化後可能得到:
若旋轉 4 次,則可以得到 [4,5,6,7,0,1,2]
若旋轉 7 次,則可以得到 [0,1,2,4,5,6,7]
注意,陣列 [a[0], a[1], a[2], ..., a[n-1]] 旋轉一次 的結果為陣列 [a[n-1], a[0], a[1], a[2], ..., a[n-2]] 。
給你一個元素值 互不相同 的陣列 nums ,它原來是一個升序排列的陣列,並按上述情形進行了多次旋轉。請你找出並返回陣列中的 最小元素 。
示例1
輸入:nums = [3,4,5,1,2]
輸出:1
解釋:原陣列為 [1,2,3,4,5] ,旋轉 3 次得到輸入陣列。
示例2
輸入:nums = [4,5,6,7,0,1,2]
輸出:0
解釋:原陣列為 [0,1,2,4,5,6,7] ,旋轉 4 次得到輸入陣列。
示例3
輸入:nums = [11,13,15,17]
輸出:11
解釋:原陣列為 [11,13,15,17] ,旋轉 4 次得到輸入陣列。
提示
n == nums.length
1 <= n <= 5000
-5000 <= nums[i] <= 5000
nums 中的所有整數 互不相同
nums 原來是一個升序排序的陣列,並進行了 1 至 n 次旋轉
程式碼
class Solution(object):
def findMin(self, nums):
# return sorted(nums)[0]
# return min(nums)
n=len(nums)
left,right=0,n-1
while left<=right:
mid=(left+right)//2
print(left,mid,right)
if nums[mid]<nums[right]:
right=mid
else:
left=mid+1
return nums[mid]