情景:在递增且不重复的数组中查找target的编号。
注意:
1.循环终止条件:left=right+1 L=R时有可能都指向target,所以L>R视为遍历完成。
2.三种情况下的操作
def search(nums, target):
left = 0
right = len(nums) - 1
while left <= right:
mid = (left + right) // 2
if target == nums[mid]:
return mid
if target < nums[mid]:
right = mid - 1
elif target > nums[mid]:
left = mid + 1
return -1
情景: 查找target的左右边界。
注意:
1.与上面的区别是在nums[mid]=target时指针仍移动
2.二分法可行性的理解:相当于把一个闭区间不断缩短,当这个区间不成立时,就找到了。
def searchleft(nums, target):
left = 0
right = len(nums) - 1
while left <= right:
mid = (left + right) // 2
if target < nums[mid]:
right = mid - 1
elif target > nums[mid]:
left = mid + 1
elif target == nums[mid]:
right = mid - 1 #中值等于target仍然是右指针左移。
#右指针左移使target相对右移,使左指针有机会指向首个target。最后总是left指向target,right在left左边
if left >= len(nums) or nums[left] != target: #target大于数组所有数(左指针一直右移,右指针不动) or target小于数组所有数(右指针一直左移,左指针不动)
return -1
return left
def searchright(nums, target):
left = 0
right = len(nums) - 1
while left <= right:
mid = (left + right) // 2
if target < nums[mid]:
right = mid - 1
elif target > nums[mid]:
left = mid + 1
elif target == nums[mid]:
left = mid + 1
if right < 0 or nums[right] != target:
return -1
return right
print(searchleft([-1,0,3,3,3,5], 3))
print(searchright([-1,0,3,3,3,5], 3))
简化版本二:
def searchRange(nums, target):
result = [-1, -1]
left, right, index = 0, len(nums) - 1, -1
while left <= right:
mid = (left + right) // 2
if nums[mid] == target:
index = mid
right = mid - 1
elif nums[mid] > target:
right = mid - 1
else:
left = mid + 1
result[0] = index
left, right, index = 0, len(nums) - 1, -1
while left <= right:
mid = (left + right) // 2
if nums[mid] == target:
index = mid
left = mid + 1
elif nums[mid] > target:
right = mid - 1
else:
left = mid + 1
result[1] = index
return result
nums = [5, 7, 7, 8, 8, 10]
target = 7
print(searchRange(nums, target))