Leetcode刷题第二天-二分查找

33. 搜索旋转排序数组 - 力扣(LeetCode)

二分查找的前提条件“数组有序

middle将数组分成左区间[left,middle)和右区间[middle,rigjht)两部分,左区间和右区间必有一个区间为有序区间

  • 左区间为有序数组
    • 如果middle数据大于target  ——> 目标数据在左区间且左区间升序 ——> 正常二分查找
    • 如果middle数据小于target  ——> 目标没有在左区间,去右区间查找(对右区间进行二分,判断左右哪边有序。。。)
  • 右区间为有序数组
    • 如果middle数据小于target ——> 目标数据在右区间且右区间有序 ——> 正常二分查找
    • 如果middle数据大于target ——> 目标数据没有在右区间,去左区间查找(对左区间进行二分。。。)
class Solution:
    def help(self,nums,left,right,target):
        while left<right:
            middle=int((left+right)/2)
            if nums[middle]==target:   
                return middle
            elif nums[middle]>target:
                right=middle
            else:
                left=middle+1
        return -1
    def search(self, nums: List[int], target: int) -> int:
        if not nums or target not in nums:    return -1
        left,right=0,len(nums)
        while left<right:
            middle=int((left+right)/2)
            if nums[left]<=nums[middle]:
                if nums[middle]>target:
                    res=self.help(nums,left,middle,target)
                    if res!=-1: return res
                    else:
                        left=middle+1
                elif nums[middle]<target:
                    left=middle+1
                else:
                    return middle
            elif nums[middle]<=nums[right-1]:
                if nums[middle]<target:
                    res=self.help(nums,middle,right,target)
                    if res!=-1: return res
                    else:
                        right=middle
                elif nums[middle]>target:
                    right=middle
                else:
                    return middle

34. 在排序数组中查找元素的第一个和最后一个位置 - 力扣(LeetCode)

正常二分查找,在[left,right)找到目标数据middle

  • 在[left,middle)区间查找,直到区间的左边界=右边界 且右边界小于等于第一次找到目标值的位置 ——> 左边界查找完成
  • 在[middle+1,right)区间查找,直到区间的左边界=右边界 ——> 右边界查找完成
class Solution:
    def searchRange(self, nums: List[int], target: int) -> List[int]:
        if not nums:    return [-1,-1]
        left,right=0,len(nums)
        res=[-1,-1]
        while left<right:
            middle=int((left+right)/2)
            if nums[middle]>target:
                right=middle
            elif nums[middle]<target:
                left=middle+1
                if left==right:
                    if right<=res[0]:
                        left,right=res[1]+1,len(nums)
            else:
                if res[0]==-1:
                    res[0],res[1]=middle,middle
                    right=middle
                if right<=res[1]:
                    res[0]=middle
                    right=middle
                    if left==right:
                        left,right=res[1]+1,len(nums)
                else:
                    res[1]=middle
                    left=middle+1
        return res     

                
                    

74. 搜索二维矩阵 - 力扣(LeetCode)

每行查找,如果target在当前行——> 在当前行进行二分

目标值比当前行[-1]数据大 ——> 目标在下面行

目标值比当前行[0]数据小 ——> 目标在上面行

查找不到 ——> 目标不在矩阵中

class Solution:
    def help(self,nums,target):
        if target>nums[-1]: 
            return 1
        if target<nums[0]:
            return -1
        left,right=0,len(nums)
        while left<right:
            middle=int((left+right)/2)
            if nums[middle]>target:
                right=middle
            elif nums[middle]<target:
                left=middle+1
            else:
                return 0
        return -2
    def searchMatrix(self, matrix: List[List[int]], target: int) -> bool:
        if not matrix:  return False
        left,right=0,len(matrix)
        while left<right:
            middle=int((left+right)/2)
            if self.help(matrix[middle],target)==0:
                return True
            elif self.help(matrix[middle],target)==1:
                left=middle+1
            elif self.help(matrix[middle],target)==-1:
                right=middle
            else:
                return False
        return False
        

 81. 搜索旋转排序数组 II - 力扣(LeetCode)

与33题不同的是,需要排除数组左边界的数据等于右边界的数据,如果存在,则两边指针同时走,直到数据不同在进行二分

class Solution:
    def help(self,nums,target):
        left,right=0,len(nums)
        while left<right:
            middle=int((left+right)/2)
            if nums[middle]==target:
                return True
            elif nums[middle]>target:
                right=middle
            else:
                left=middle+1
        return False
    def search(self, nums: List[int], target: int) -> bool:
        if not nums:    return False
        left,right=0,len(nums)
        while left<right:
            if nums[left]==nums[right-1]:
                if nums[left]==target:
                    return True
                left+=1
                right-=1
                continue
            middle=int((left+right)/2)
            if nums[left]<=nums[middle]:
                if self.help(nums[left:middle+1],target):
                    return True
                else:
                    left=middle+1
            else:
                if self.help(nums[middle:right],target):
                    return True
                else:
                    right=middle
        return False

 153. 寻找旋转排序数组中的最小值 - 力扣(LeetCode)

33、81同类型

class Solution:
    def findMin(self, nums: List[int]) -> int:
        if not nums:
            return None
        left,right=0,len(nums)
        min_num=nums[0]
        while left<right:
            middle=int((left+right)/2)
            if nums[left]<nums[middle]:
                min_num=min(nums[left],min_num)
                left=middle+1
            else:
                min_num=min(min_num,nums[middle])
                right=middle
        return min_num
        

 

posted @ 2024-12-31 22:00  小小小茹茹  阅读(28)  评论(0)    收藏  举报