二分查找
二分查找的就像我们喝酒时候猜数字一样,如 100 中猜一个数字 28
甲: 请猜我心里想的数字(28),范围是 1 到 100 乙: 比 50 大还是小 (1-50) 甲: 小 乙: 比 25 大还是小 (1-25) 甲: 大 乙: 比 37 大还是小 (26-49) 甲: 小 乙: 比 37 大还是小 (26-37) 甲: 小 乙: 比 31 大还是小 (26-37) 甲: 小 乙: 是不是 28 (26-31) 甲: 对
如果用遍历查找的话需要 100 次, 用二分法 6 次, 最多 7 次就可以猜到
简单的二分法 (没有考虑重复数字)
给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1。
来源:力扣(LeetCode)https://leetcode-cn.com/problems/binary-search
class Solution(object): def search(self, nums, target): low, high = 0, len(nums)-1 # 注意是小于等于 while low <= high: mid = low + (high-low)//2 if nums[mid] == target: # 找到了目标, 不用考虑重复的话就可以直接返回 mid 了 return mid elif nums[mid] > target: # 目标在中间位置的左边,改变最高位的位置 high = mid - 1 else: # 目标在中间位置的右边,改变最低位的位置 low = mid + 1 return -1
二分法进阶 (要考虑重复数字,找到特定数字的第一个或则最后一个)
请实现有重复数字的升序数组的二分查找
给定一个 元素有序的(升序)整型数组 nums 和一个目标值 target ,写一个函数搜索 nums 中的第一个出现的target,如果目标值存在返回下标,否则返回 -1
来源:牛客(LeetCode)
分析一下有什么不一样
如果二分法第一次找到了目标数字,这个数字可能是第一个,可能是第 N 个,也可能是最后一个, 怎么找到题目中要求的第一个呢
答案是: 缩小 high 的范围继续找,即index = -1 if nums[mid] == target: index = mid high = mid - 1重复整个过程就会找到第一个特定的数字了
class Solution(object): def search(self, nums, target): index, low, high = -1, 0, len(nums)-1 while low <= high: mid = low + (high-low)//2 if nums[mid] == target: index = mid high = mid - 1 elif nums[mid] > target: # 继续找 mid 的左边 high = mid - 1 else: # 继续找 mid 的右边 low = mid + 1 return index
思考:怎么找第 N 个或则最后一个 target 呢