二分查找——边界问题(leetcode 34,Offer 53

"""
寻找决策边界分为寻找左侧边界、右侧边界
寻找左侧边界,压缩右边界(当mid=target缩小right)
寻找右侧边界,压缩左边界(当mid=target缩小left)
"""

#寻找左侧边界
def query_left_target_boundary_v1(list_num, target):
left = 0
right = len(list_num) - 1
while left <= right:
mid = left + int((right-left)/2)
if list_num[mid] > target:
right = mid - 1
elif list_num[mid] < target:
left = mid + 1
elif list_num[mid] == target:
right = mid - 1 #缩小right,逼近左侧边界
if left >= len(list_num) or list_num[left] != target: #针对特殊的左侧边界,进行特殊的判断
return -1
return left

def query_left_target_boundary_v2(list_num, target):
left = 0
right = len(list_num)
while left < right:
mid = left + int((right-left)/2)
if list_num[mid] > target:
right = mid
elif list_num[mid] < target:
left = mid + 1
elif list_num[mid] == target:
right = mid
if left >= len(list_num) or list_num[left] != target:
return -1
return left

#寻找右侧边界
def query_right_target_boundary_v1(list_num, target):
left = 0
right = len(list_num) - 1
while left <= right:
mid = left + int((right-left)/2)
if list_num[mid] > target:
right = mid - 1
elif list_num[mid] < target:
left = mid + 1
elif list_num[mid] == target:
left = mid + 1 #缩小left,逼近右侧侧边界
if right < 0 or list_num[right] != target: #针对特殊的右侧边界,进行特殊的判断
return -1
return right

def query_left_target_boundary_v2(list_num, target):
left = 0
right = len(list_num)
while left < right:
mid = left + int((right-left)/2)
if list_num[mid] > target:
right = mid
elif list_num[mid] < target:
left = mid + 1
elif list_num[mid] == target:
left = mid + 1
if right <= 0 or list_num[right - 1] != target:
return -1
return right - 1



"""
剑指 Offer 53 - I. 在排序数组中查找数字 I
统计一个数字在排序数组中出现的次数。

示例 1:
输入: nums = [5,7,7,8,8,10], target = 8
输出: 2

示例 2:
输入: nums = [5,7,7,8,8,10], target = 6
输出: 0

"""
给定一个按照升序排列的整数数组nums, 和一个目标值target。找出给定目标值在数组的开始位置和结束位置(leetcode 34)
"""

"""
解题思路:这道题和find_target_number类似,也是考虑求出目标值的左右边界
"""
def find_target_first_end(nums, target):
#找出左侧边界的索引
left_index = find_left_index(nums, target)
if left_index == -1:
return [-1, -1]
right_index = find_right_index(nums, target)
return [left_index, right_index]

def find_left_index(nums, target):
left = 0
right = len(nums)
while left < right:
mid = left + int((right - left) / 2)
if nums[mid] >= target:
right = mid
else:
left = mid + 1
if left >= len(nums) or nums[left] != target:
return -1
return left

def find_right_index(nums, target):
left = 0
right = len(nums)
while left < right:
mid = left + int((right - left) / 2)
if nums[mid] <= target:
left = mid + 1
else:
right = mid
if right <= 0 or nums[right - 1] != target:
return -1
return right - 1

if __name__ == "__main__":
nums = [5,7,7,8,8,10]
target = 10
res = find_target_first_end(nums, target)
print(res)


解题思路:
按照二分查找的方式,找到目标值的左右边界的索引 然后用右边界-左边界+1
"""
class Solution(object):
def search(self, nums, target):
left = 0
right = len(nums)
target_left = -1
target_right = -1
#找出目标值的左侧边界
while left < right:
mid = left + int((right - left) / 2)
if nums[mid] > target:
right = mid
elif nums[mid] < target:
left = mid + 1
elif nums[mid] == target:
right = mid

if left >= len(nums) or nums[left] != target:
target_left = -1
else:
target_left = left
原文地址:https://www.cnblogs.com/tomorrow-hope/p/15476681.html