二分法查找

news/2025/1/8 20:39:26/文章来源:https://www.cnblogs.com/xiaoxianglu/p/18660507

二分法查找算法应用的条件:

  • 数组按照顺序排列【基础】;
  • 数组中没有重复的元素【否则返回值元素的下标不唯一】;

二分法查找主要难点在于边界条件的确定,常见的区间的定义一般有两种:左闭右闭,即 [left, right],或者左闭右开,即 [left, right);

第一种:左闭右闭,即 [left, right],代码如下:

class Solution {public int search(int[] nums, int target) {int res = -1;int right = nums.length -1;int left = 0;while (left <= right) {            //重点在于循环条件的确定;int middle = left + ((right - left) >> 1);if (nums[middle] > target) {right = middle -1;}else if (nums[middle] < target) {left = middle +1;}else {res = middle;break;}}return res;}
}

第二种:左闭右开,即 [left, right),代码如下:

class Solution {public int search(int[] nums, int target) {int res = -1;int right = nums.length;int left = 0;while (left < right) {				//循环条件的确定int middle = left + ((right - left) >> 1);if (nums[middle] > target) {right = middle;}else if (nums[middle] < target) {left = middle +1;}else {res = middle;break;}}return res;}
}

两种方法的区别:

  • 左闭右闭,即 [left, right],
    • 当left = right时,仍然要进入循环;
    • 当没有找到 target 值时,循环体结束后,left - right = 1
  • 左闭右开,即 [left, right),
    • 当left = right时,跳出循环;
    • 当没有找到 target 值时,循环体结束后,right = left

此外,涉及到边界条件问题:

  • 例如:在排序数组中查找元素的范围【数组非严格单调,存在重复元素】,此时,需要确定范围的左右区间;

  • 区间的确定:

    \[左区间:nums[pos−1]<target≤nums[pos]\\ 右区间:nums[pos−1]≤target<nums[pos] \]

  • 当为左闭右闭,即 [left, right]时:

    public int getRight(int[] nums, int target) {int res = -1;int right = nums.length - 1;int left = 0;while (right >= left) {int middle = left + ((right - left) >> 1);if (nums[middle] > target) {right = middle -1;}else {left = middle + 1;}}res = left;}return res;}
    public int getLeft(int[] nums, int target) {int res = -1;int right = nums.length - 1;int left = 0;while (right >= left) {int middle = left + ((right - left) >> 1);if (nums[middle] < target) {left = middle + 1;}else {right = middle -1;}}res = right;return res;}
    
    • 循环体结束后,left - right = 1

    • 当数组不存在对应target元素时,左右区间产生的left,right完全一样;

    • 当数组中存在一个元素时

      • left - right = 1

      • \(right_{左区间}\) = \(left_{右区间}\)

      • 由上面两个公式,可得:

        \(right_{右区间} - left_{左区间}=2\)

    • 当数组中存在多个元素时,同理:

      • \(right_{右区间} - left_{左区间}=2 + 元素个数\)
    • 统一范围:[\(left_{左区间} +1, right_{右区间} -1\)],

  • 当为左闭右开,即 [left, right)时,代码如下:

        public int getRight(int[] nums, int target) {int res = -1;int right = nums.length;int left = 0;while (right > left) {int middle = left + ((right - left) >> 1);if (nums[middle] > target) {right = middle;}else {left = middle + 1;}}res = left;return res;}public int getLeft(int[] nums, int target) {int res = -1;int right = nums.length;int left = 0;while (right > left) {int middle = left + ((right - left) >> 1);if (nums[middle] < target) {left = middle + 1;}else {right = middle;}}res = right;return res;}
    
    • 循环体结束后,left = right,并且最后一步骤基本都是 left = left + 1
    • 当数组不存在对应target元素时,
      • target元素在数组的范围内,但不存在时,left = right=靠近较大值的索引,例如:nums = [0, 0, 2, 2],target = 1, \(left = right = 2_{index}\)
      • target元素不在数组的范围内,且不存在时,left = right = 0 or nums.length
    • 当数组中存在一个元素时:
      • 左区间:$left_{右区间} = right_{右区间} $ = 元素索引;
      • 右区间: $left_{右区间} = right_{右区间} $ = 元素索引 + 1;
      • 因为当left和right相邻的时候,middle取的是 left的值作为索引,而左闭右开,则还会执行一次;
    • 当数组中存在多个元素时,
      • 左区间:$left_{右区间} = right_{右区间} $ = 元素索引;
      • 右区间: $left_{右区间} = right_{右区间} $ = 元素索引 + 元素个数;
    • 统一范围:[$left_{左区间} , right_{右区间} -1 $];

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/866062.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

mongodb windows zip安装并服务自启动

1.下载并解压。2.新建文件/文件夹 data/db 目录 logs/mongod.log 文件 conf/mongod.conf 文件 3.编辑conf/mongod.conf文件 systemLog:destination: filelogAppend: truepath: F:/mongodb-win32-x86_64-windows-6.0.20-rc3/logs/mongod.logstorage:dbPath: F:/mongodb-win32-x…

Linux通过端口找到对应的服务

首先执行netstat -tulnp | grep <端口号>例如:netstat -tulnp | grep :80参数解释:-t: 显示 TCP 连接(只显示TCP协议的端口信息)。 -u: 显示 UDP 连接(只显示UDP协议的端口信息)。 -l: 显示正在监听(Listening)状态的端口(只显示处于监听状态的端口)。 -n: 以数…

2025新春源码免费送

我们常常在日常生活中感到时间过得异常缓慢,仿佛未来遥不可及。然而,当我们回过头去审视过去,才发现时间早已悄然溜走,许多曾经等待的日子已经过去。时间总是在不经意间流逝,让人意识到它的宝贵和不可逆转。 尽管如此,我们依然应对未来保持从容的态度。生活充满了无数的可…

2025.1.8 鲜花

Nim 的变种Nim 的变种グランドエスケープ 空飛ぶ羽根と引き換えに 繋ぎ合う手を選んだ僕ら 没有选择飞翔的翅膀 而是选择十指相扣的我们 それでも空に魅せられて 夢を重ねるのは罪か 却仍然向往着天空 反复做着同样的梦 这有错吗 夏は秋の背中を見て その顔を思い浮かべる 夏…

CTF 之 Crypto (Cryptography) 学习笔记

CTF 之 Crypto (Cryptography) Chapter 0. 前置知识 群 (Group) 给定一个集合 \(G\neq \emptyset\) 以及二元代数运算 \(\circ\),若满足:封闭性 (Closure):\(\forall u,v\in G\),\(u\circ v\in G\); 结合律 (Associativity):\(\forall u,v,w\in G\),\((u\circ v)\circ w…

(2025自测有效!)全网最好的python配置教程【非常非常适合小白】

前几天我的电脑刚刚重装,把python重新配置了一下。 1.Python环境部署Python3 可应用于多平台包括 Windows、Linux 和 Mac OS X。 Python官网:https://www.python.org/ 进入官网在导航栏选择Dowmloads,选择所使用的系统(以Windows为例) 进入Windows下载页之后选择需要下载的…

写一个支持折叠、有缩进、代码高亮、离线的,方便部署的、易用的、优雅的json格式化查看工具(附html完整代码)

缘由 网上的在线json格式化有很多,但我是个有追求的人。在线的很难同时支持折叠、有缩进线、代码高亮、离线的,方便部署的、易用的、不请求后端(为了安全)的json格式化工具。 去Github上找项目,华而不实的东西占半个屏幕,格式化json要点好几下,一个json格式化工具npm安装…

AGC041F Histogram Rooks

我不知道啊,我只是觉得容斥很好玩。一个朴素的想法是容斥:考虑钦定 \(S\) 集合的位置没有被车覆盖,则答案是 \((-1)^{|S|}2^{c}\),其中 \(c\) 是可以放车的位置,可以直接 dp 做到 \(\mathrm{O}(2^n \text{poly}(n))\),但是难以优化。 延续容斥的想法,注意到钦定一个位置…

rust学习十六.1、并发-乱弹和一个简单并发例子

如书本作者所言,并发编程在绝大部分语言中,都是相对复杂和困难的。 所以,涉及的内容会相对多一些,所涵盖的内容绝对不是几篇文章所可以容纳的。 权当一个乱弹琴! 和此系列的其它文章一样,本文的内容绝大部分来自于相关书籍,本人做了一些摘裁的工作,取我所需!一、无畏并…

解决jenkins git 拉取代码超时问题

jenkins默认的是时间是10分钟,在git fetch时候超过10分钟了就报错失败了,可在项目源码管理 新增 advance clone behaviours

Java Bluetooth 蓝牙通讯 BlueCove 扫描附近的蓝牙设备

目录BlueCove项目概述BlueCove API架构API的设计原则和实现方式关键类和方法的功能描述测试代码获取本机(PC)蓝牙扫描蓝牙 BlueCove项目概述 BlueCove是一个开源的蓝牙协议栈实现,旨在为Java开发者提供一个全面的、易于使用的API,从而在应用程序中实现蓝牙功能。该项目支持多…