1. 程式人生 > 其它 >【每日演算法】二分查詢法II

【每日演算法】二分查詢法II

目錄

模板

left,right=1,n
while left<=right:
    mid=left+(right-left)//2
    if 條件:
        right=mid+1
    else:
        left=mid-1
  1. 定義左右邊界
  2. 左邊界小於右邊屆時進入迴圈體
  3. 取中間數,使用left+(right-left)//2是防止越界的問題
  4. 根據業務條件不斷的向中間移動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]