二分搜索

介绍

二分查找适用于已经排序的序列,通过对搜索区间折半的方式查找目标元素。

基本的二分搜索

基本的二分查找适用于在已经排序的无重复元素的序列中,查找一个目标值。。

思路

查找左边界的二分搜索,假设查找区间为 [0,n] ,那么:

  • 如果中间元素 nums[mid] 大于目标值,右指针移动到 mid1 位置;

  • 如果中间元素 nums[mid] 小于目标值,左指针移动到 mid+1 的位置;

  • 如果中间元素 nums[mid] 等于目标值,则结束查找,返回结果;

注意:如果遍历完整个序列,都没有找到匹配的值,那说明序列中不包含目标值。

代码实现

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可能包含重复元素,就需要换一种方式查找。
例如,我们要从升序的序列nums=[1,2,3,4,5,5,5,6,6,7,8],中查找第一个出现的元素5的序号,那么就要用到查找左边界的二分搜索方法。

思路

查找左边界的二分搜索,假设查找区间为 [0,n1],那么:

  • 如果中间元素 nums[mid] 大于等于目标值,下一个查找区间为:[left,mid1],右指针移动到 mid1 位置;

  • 如果中间元素 nums[mid] 小于目标值,下一个查找区间为:[mid+1,right],左指针移动到 mid+1 的位置。

注意,这里的循环条件,极端情况下 left 最多可以等于 n。

循环的退出条件为:left=right+1,此时,如果目标值存在,则:nums[left]target,因此,目标值的右边界为:nums[left]

如果查找完所有的元素后,左指针针超出数组边界,或者,左指针指向的元素不等于目标值,则,原始数组中不存在目标值;否则,就返回左指针

代码实现

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;
}
}

查找右边界的二分搜索

同理,如果我们要从升序序列中查找出最后一次出现的元素,就要通过查找右边界的二分搜索方法。

思路

查找右边界的二分搜索,假设查找区间为 [0,n1] ,那么:

  • 如果中间元素 nums[mid] 大于目标值,下一个查找区间为:[left,mid1],因此,右指针移动到 mid1 位置;

  • 如果中间元素 nums[mid] 小于等于目标值,下一个查找区间为:[mid+1,right],左指针移动到 mid+1 的位置;

循环的退出条件为:left=right+1,此时,如果目标值存在,则:nums[right]target,因此,目标值的右边界为:nums[right]

如果指针 right 不在数组内,或者,指针 right 指向的元素不等于目标值,那么原始数组不包含目标值,否则,就返回指针 right

代码实现

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 中国大陆许可协议进行许可。

posted @   LARRY1024  阅读(40)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
💬
评论
📌
收藏
💗
关注
👍
推荐
🚀
回顶
收起
  1. 1 404 not found REOL
404 not found - REOL
00:00 / 00:00
An audio error has occurred.