当前位置:首页 > 后端开发 > 正文内容

【知识点】二分查找的区间到底是开仍是闭?

邻居的猫1个月前 (12-09)后端开发1229

二分查找的区间究竟是开仍是闭?

在这两个月的时刻里,我好像没有产出任何的有关常识点的文章,大多数都是题解相关的内容。以至于许多人觉得 Macw07 “失踪”了。本文是我来到北美之后的第一篇常识点文章,请咱们多多关照。

这次不讲难的常识点了,讲一个咱们都了解的,但又十分令人抓毛的算法:二分查找和二分答案算法

导言 Introduction

留意:本文仅针对了解过二分查找根本算法原理的用户集体,若您从未触摸过或了解过该算法,请先学习根底的二分查找算法。

二分查找算法是咱们一个再了解不过的算法了,二分查找算法能够在一个 有序数列 中高效地查找某个或多个特定的目标值。一般来说,二分查找的时刻杂乱度在 \(O(\log_2 N))\) 等级。二分算法十分适合在大数据集上完成快速查询。与此同时,除了根本的二分查找算法,它的许多变种也被广泛运用于各种场景,比方求最大值、最小值,甚至在杂乱的数据结构中优化数据的查找功能。

许多同学必定在学习完根本的二分查找后一向有一个疑问:我究竟该怎么设置 \(L\)\(R\) 的区间闭合状况?什么时分需求输出 \(L\)\(R\),为什么有时分还需求 \(+1\)\(\text{Mid}\) 究竟保存的是什么东西?etc.

事实上,区间开闭的变量界说 确实是一个中心且简单混杂的问题,在 CSP 考试中也常考此常识点,因而本文将要点环绕区间开闭的变量界说来打开。

在深化评论区间开闭之前,有必要回忆一下二分查找的根本原理。二分查找经过重复将查找区间分红两半,逐渐缩小目标值地点的规模,直到找到目标值或确认其不存在。具体过程如下:

  1. 初始化:设定查找区间的左右鸿沟 \(L\)\(R\)

  2. 核算中点:核算中点 \(M = L + \dfrac{R - L}{2}\)

  3. 比较

    :将目标值与中点元素进行比较。

    • 若持平,回来中点方位。
    • 若目标值小于中点元素,缩小查找区间至左半部分。
    • 若目标值大于中点元素,缩小查找区间至右半部分。
  4. 重复:重复上述过程,直到找到目标值或查找区间为空。

开区间/闭区间 Open Interval/Closed Interval

在文章开端,先了解一下区间的开闭性。

开区间

界说:开区间表明区间的端点 不包含在区间内,用小括号 \(()\) 表明。

示例:\((2, 5)\) 表明一切介于 \(2\)\(5\) 之间的数,但不包含数字 \(2\)\(5\)

闭区间

界说:开区间表明区间的端点 包含在区间内,用方括号 \([]\) 表明。

示例:\([2, 5]\) 表明一切介于 \(2\)\(5\) 之间的数,并且包含数字 \(2\)\(5\)

半开区间/半闭区间

界说:半开区间或半闭区间表明区间的一个端点包含在内,另一个端点不包含在内。

示例:\((2, 5]\) 表明一切介于 \(2\)\(5\) 之间的数,且包含数字 \(5\),但不包含数字 \(2\)

区间类型 表明方法 是否包含左端点 \(a\) 是否包含右端点 \(b\)
开区间 \((a, b)\)
闭区间 \([a, b]\)
左开右闭 \((a, b]\)
左闭右开 \([a, b)\)

区间开闭的类型 Interval Categories

在完成二分查找的时分,区间的界说是最常见的一个问题,你或许会看到过以下不同的区间开闭性的界说:

  1. 左开右开 \((\text{left}, \text{right})\)
  2. 左闭右闭 \([\text{left}, \text{right}]\)
  3. 左开右闭 \((\text{left}, \text{right}]\)
  4. 左闭右开 \([\text{left}, \text{right})\)

一般来说,咱们一般会挑选【左闭右开】或许【左闭右闭】的区间界说,所以本文也就侧重环绕这两个部分解说。但关于不同的界说区间,假如稍有不小心,就简单使代码进入 死循环

左闭右闭区间

界说:查找区间包含 leftright,即 leftright 都或许是目标值。

退出条件left > right,表明查找区间为空。

左闭右闭区间的二分查找的常见写法如下:

while (left <= right) { // 留意是 <=
    int mid = left + (right - left) / 2;
    if (nums[mid] == target) {
        return mid;
    } else if (nums[mid] < target) {
        left = mid + 1; // [mid+1, right]
    } else {
        right = mid - 1; // [left, mid-1]
    }
}

左闭右开区间

界说:查找区间包含 left 但不包含 right,即目标值或许是 left,但不或许是 right

退出条件:当 left == right 时,表明查找区间为空。

左闭右开区间的二分查找的常见写法如下:

while (left < right) { // 留意是 <
    int mid = left + (right - left) / 2;
    if (nums[mid] == target) {
        return mid;
    } else if (nums[mid] < target) {
        left = mid + 1; // [mid+1, right)
    } else {
        right = mid; // [left, mid)
    }
}

两种区间的迭代过程中的差异 Differences During Iterating

left 的更新:

  • 左闭右闭left = mid + 1,由于 mid 现已被查看过了,mid+1 开端的新区间仍是闭区间。
  • 左闭右开left = mid + 1,坚持 right 的开区间性质。

right 的更新:

  • 左闭右闭right = mid - 1,由于 mid 现已被查看过了,mid-1 确保了闭区间不重复。
  • 左闭右开right = mid,将 mid 扫除,确保开区间不包含 right

退出条件:

  • 左闭右闭:循环完毕条件为 left > right
  • 左闭右开:循环完毕条件为 left == right

两种区间的优缺点 Pros & Cons

左闭右闭的有点

  1. 直观易懂:包含 leftright 的写法愈加挨近天然语言的描绘,例如 “在 \([left, right]\) 区间查找目标值”。
  2. 处理小区间:关于某些需求特别处理的小区间问题,左闭右闭能够更简单描绘逻辑。

左开右闭的长处

防止数组越界:运用左闭右开区间,right 永远是无效方位,不会直接拜访数组越界的索引。

逻辑一致性:左闭右开区间的规模在迭代过程中能够安稳坚持逻辑明晰,简单与数学符号对应。

代码简练:由于退出条件是 left == right,许多情况下能够直接用 left 回来成果,无需做出额定查看。

实践运用中的挑选 Choosing the Right Interval in Practice

在实践运用中,挑选运用左闭右闭仍是左闭右开区间,往往取决于具体问题的需求和个人习气。以下是一些辅导准则:

  1. 数组索引:在处理数组索引时,左闭右开区间愈加天然,由于数组的索引从 0n-1,左闭右开能够防止 n 的无效拜访。
  2. 规模区分:当需求频频区分规模时,左闭右开区间的逻辑更明晰,减少了混杂和过错。
  3. 鸿沟条件:假如问题中涉及到清晰的鸿沟条件,如查找第一个或最终一个满意条件的元素,挑选适宜的区间类型能够简化逻辑。

典型例题剖析 Exemplars

1. 在数组中查找目标值,回来索引

左闭右闭完成:

int binarySearch(vector<int>& nums, int target) {
    int left = 0, right = nums.size() - 1;
    while (left <= right) {
        int mid = left + (right - left) / 2;
        if (nums[mid] == target) {
            return mid;
        } else if (nums[mid] < target) {
            left = mid + 1;
        } else {
            right = mid - 1;
        }
    }
    return -1;
}

左闭右开完成:

int binarySearch(vector<int>& nums, int target) {
    int left = 0, right = nums.size();
    while (left < right) {
        int mid = left + (right - left) / 2;
        if (nums[mid] == target) {
            return mid;
        } else if (nums[mid] < target) {
            left = mid + 1;
        } else {
            right = mid;
        }
    }
    return -1;
}

2. 在有序数组中找到目标值的刺进方位

综上所述,左闭右开更适合这一场景,由于它的区间逻辑愈加贴合“鸿沟”问题:

int searchInsert(vector<int>& nums, int target) {
    int left = 0, right = nums.size();
    while (left < right) {
        int mid = left + (right - left) / 2;
        if (nums[mid] < target) {
            left = mid + 1;
        } else {
            right = mid;
        }
    }
    return left; // 回来刺进方位
}

杂乱度剖析 Complexity Analysis

二分查找的时刻杂乱度为 \(O(\log_2 N)\),空间杂乱度为 \(O(1)\)。这种高效性使得二分查找在处理大规模数据时表现出色。但是,二分查找的前提条件是数据有必要是有序的,这在某些情况下或许需求额定的排序时刻。

相关标题 Practice Problems

能够在阅览本文后自己实践一下以下标题:

  1. 查找最挨近的元素 在一个升序序列中,查找与给定值最挨近的元素。
  2. 二分法求函数的零点 已知函数在某区间内有且只要一个根,运用二分法求出该根。
  3. 查找 x 给定一个升序序列(元素均不重复),在该序列中查找指定的值,若存在则输出对应的下标,不然输出 \(-1\)
  4. 二分查找 在 \(N\) 个从小到大摆放且不重复的整数中,快速找到指定的数字 \(t\),若找不到则输出 \(-1\)

扫描二维码推送至手机访问。

版权声明:本文由51Blog发布,如需转载请注明出处。

本文链接:https://www.51blog.vip/?id=197

分享给朋友:

“【知识点】二分查找的区间到底是开仍是闭?” 的相关文章

全网最适合入门的面向对象编程教程:60 Python面向对象归纳实例-传感器数据实时绘图器

全网最适合入门的面向对象编程教程:60 Python面向对象归纳实例-传感器数据实时绘图器

全网最适合入门的面向目标编程教程:60 Python 面向目标归纳实例-传感器数据实时绘图器 摘要: 本文将结合之前内容完结模仿一个传感器系统软件,包括三个线程:传感器线程生成数据并经过串口发送给主机进程;主机进程经过串口接纳指令,进行数据滤波和处理后,将处理结果发送给绘图线程;绘图线程担任接纳数...

PHP和Composer做语法转化东西

PHP和Composer做语法转化东西

原文地址:https://www.mengze2.cn/post/5/ 最近不是把博客的一些文章从和HTML转到Markdown了吗,由于之前换到了wordpress所以是HTML,可是这些文章再typecho无法被解析,于是就计划开发一个Markdown2HTML东西 下面使我的开发笔记,或许比...

处理Windows中文用户名导致的Dart AOT编译失利问题

处理Windows中文用户名导致的Dart AOT编译失利问题

Windows中文用户名导致的Dart AOT编译失利   我的微软账户一向运用中文用户名,Windows会把这个用户名作为用户文件夹的称号,并且很难修正. 这就导致但凡放在这个途径下的文件都得有一个带中文的绝对途径. Dart 编译时或许由于这儿的中文字符而犯错.   问题呈现时的操作体系及D...

Flutter/Dart第04天:Dart异步编程(Future和async/await)

Flutter/Dart第04天:Dart异步编程(Future和async/await)

Dart官网代码实验室:https://dart.dev/codelabs/async-await 重要阐明:本博客依据Dart官网代码实验室,但并不是简略的对官网文章进行翻译,我会依据个人研制经历,在掩盖官网文章核心内容情况下,参加自己的一些扩展问题和问题演示和总结,包含称号解说、运用场景阐明、代...

怎么打开php文件,全面指南

在Windows系统中,你可以通过以下步骤打开PHP文件:1. 安装PHP环境:确保你的计算机上安装了PHP环境。你可以从PHP官方网站下载并安装PHP。2. 安装文本编辑器:安装一个文本编辑器,如Notepad 、Sublime Text或Visual Studio Code等。这些编辑器支持多...

java编程题,从基础到进阶

好的,请您提供具体的Java编程题目。Java编程题实战解析:从基础到进阶Java作为一门广泛应用于企业级应用、Android开发、大数据处理等领域的编程语言,掌握Java编程能力对于程序员来说至关重要。本文将带您通过一系列Java编程题,从基础语法到进阶技巧,一步步提升您的编程能力。1. 输出He...