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
每行查找,如果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

浙公网安备 33010602011771号