二分搜索
介绍
二分查找适用于已经排序的序列,通过对搜索区间折半的方式查找目标元素。
基本的二分搜索
基本的二分查找适用于在已经排序的无重复元素的序列中,查找一个目标值。。
思路
查找左边界的二分搜索,假设查找区间为
-
如果中间元素
大于目标值,右指针移动到 位置; -
如果中间元素
小于目标值,左指针移动到 的位置; -
如果中间元素
等于目标值,则结束查找,返回结果;
注意:如果遍历完整个序列,都没有找到匹配的值,那说明序列中不包含目标值。
代码实现
from typing import List def binary_search(nums: List[int], target: int): left, right = 0, len(nums) - 1 while left <= right: mid = left + (right - left) // 2 if nums[mid] == target: return mid elif nums[mid] < target: left = mid + 1 else: right = mid - 1 return -1 if __name__ == "__main__": print(binary_search([1, 2, 3, 4, 5, 6, 7, 8], 6))
查找左边界的二分搜索
如果已经排序的序列包含重复元素,即待查找的目标值target可能包含重复元素,就需要换一种方式查找。
例如,我们要从升序的序列
思路
查找左边界的二分搜索,假设查找区间为
-
如果中间元素
大于等于目标值,下一个查找区间为: ,右指针移动到 位置; -
如果中间元素
小于目标值,下一个查找区间为: ,左指针移动到 的位置。
注意,这里的循环条件,极端情况下 left 最多可以等于 n。
循环的退出条件为:
如果查找完所有的元素后,左指针针超出数组边界,或者,左指针指向的元素不等于目标值,则,原始数组中不存在目标值;否则,就返回左指针。
代码实现
public class BinarySearch { static int leftBinarySearch(int[] nums, int target) { int left = 0, right = nums.length - 1; while (left <= right) { int mid = left + (right - left) / 2; // 如果区间的中点值大于等于目标值,要移动右指针 if (nums[mid] >= target) { right = mid - 1; } else { left = mid + 1; } } if (left > nums.length - 1 || nums[left] != target) { return -1; } return left; } }
查找右边界的二分搜索
同理,如果我们要从升序序列中查找出最后一次出现的元素,就要通过查找右边界的二分搜索方法。
思路
查找右边界的二分搜索,假设查找区间为
-
如果中间元素
大于目标值,下一个查找区间为: ,因此,右指针移动到 位置; -
如果中间元素
小于等于目标值,下一个查找区间为: ,左指针移动到 的位置;
循环的退出条件为:
如果指针
代码实现
public class BinarySearch { static int rightBinarySearch(int[] nums, int target) { int left = 0, right = nums.length - 1; while (left <= right) { int mid = left + (right - left) / 2; // 如果区间的中点值小于等于目标值,要移动左指针 if (nums[mid] <= target) { left = mid + 1; } else { right = mid - 1; } } if (right < 0 || nums[right] != target) { return -1; } return right; } }
本文作者:LARRY1024
本文链接:https://www.cnblogs.com/larry1024/p/16897559.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步