基础算法-整数二分

news2024/9/21 22:56:58

基础算法-整数二分

基本思想——折半
二分法的基本思想比较简单,是用来在数组当中查找特定元素的算法。
二分可以分为整数二分和浮点二分,本文主要介绍整数二分。

具体步骤

首先,从数组的中间元素开始搜索,如果该元素恰好是目标元素,则搜索过程结束,否则继续执行。
如果目标元素大于/小于中间元素,则在数组大于/小于中间元素的那一半区域查找,然后重复上一步的操作。
如果某一步数组为空,则表示找不到目标元素。
边界更新的两种方式


当 mid=l+r+1>>1 时,查找值指向箭头2位置,检查 mid 是否满足红色部分性质,如果成立的话,mid 便在红色区域当中,此时,查找值便在区域 [mid,r] 里面,此时更新边界的方法为 l=mid 。如果不成立的话,mid 便在蓝色区域当中,此时查找值便在区域 [l,mid-1] 里面,此时更新边界的方法为 r=mid-1 。
当 mid=l+r>>1 时,查找值指向箭头1位置,检查 mid 是否满足蓝色部分性质,如果成立的话,mid 便在蓝色区域当中,此时,查找值便在区域 [l,mid] 里面,这里要注意包含边界,因为我们的查找值可能就是边界,此时更新边界的方法为 r=mid 。如果不成立的话,mid 便在红色区域当中,此时查找值便在区域 [mid,r] 里面,此时更新边界的方法为 l=mid+1 。

注意事项

二分法特别需要注意左右两端的边界问题,如果发生问题绝大部分都是由边界产生的,因此本文提供三种模板来应对不同情况下的二分问题。
单调性与二分法并没有直接关系。如果题目具有单调性的话我一定可以使用二分法,但是我可以使用二分法的题目不一定非得由单调性。
C++ 整数除法是 向下取整。

题目描述

给定一个按照升序排列的长度为 n 的整数数组,以及 q 个查询。
对于每个查询,返回一个元素 k 的起始位置和终止位置(位置从 0 开始计数)。
如果数组中不存在该元素,则返回 -1 -1。

输入格式
第一行包含整数 n 和 q,表示数组长度和询问个数。
第二行包含 n 个整数(均在 1∼10000 范围内),表示完整数组。
接下来 q 行,每行包含一个整数 k,表示一个询问元素。

输出格式
共 q 行,每行包含两个整数,表示所求元素的起始位置和终止位置。
如果数组中不存在该元素,则返回 -1 -1。

数据范围
1≤n≤100000
1≤q≤10000
1≤k≤10000

输入样例
6 3
1 2 2 3 3 4
3
4
5

输出样例
3 4
5 5
-1 -1

实现方法

1. 方法一(模板)

#include <bits/stdc++.h>
using namespace std;

const int N=100000;
int n,m; 
int q[N];
int main()
{
    cin>>n>>m;
    for (int i = 0; i < n; i ++ )
    {
        cin>>q[i];
    }
    while (m -- )
    {
        int x;
        cin>>x;

        int l = 0, r = n - 1;
        while (l < r)
        {
            int mid = l + r >> 1;
            if (q[mid] >= x)
            {
                r = mid;
            }
            else
            {
                l = mid + 1;
            }
        }
        if (q[l] != x)
        {
            cout << "-1 -1" << endl;
        }
        else
        {
            cout << l << ' ';
            int l = 0, r = n - 1;
            while (l < r)
            {
                int mid = l + r + 1 >> 1;
                if (q[mid] <= x)
                {
                    l = mid;
                }
                else
                {
                    r = mid - 1;
                }
            }
            cout << l << endl;
        }
    }
    system("pause");
    return 0;
}

2. 方法二(不需要考虑边界)

详细思路请见 B站up主五点七边视频

#include <bits/stdc++.h>
using namespace std;

const int N=100000;
int n,m; 
int q[N];
int left_border(int x)
{
    int l = -1, r = n;
    while (l + 1 != r)
    {
        int mid = (l + r) >> 1;
        if (x > q[mid]) l = mid;
        else r = mid;
    }

    if (r == n || q[r] != x)
    {
        return -1;
    }
    else
    {
        return  r;
    }
}
int right_border(int x)
{
    int l = -1, r = n;
    while (l + 1 != r)
    {
        int mid = (l + r) >> 1;
        if (x < q[mid])
        {
            r = mid;
        }
        else 
        {
            l = mid;
        }
    }

    if (l == -1 || q[l] != x)
    {
        return -1;
    }
    else
    {
        return l;
    }
}
int main()
{
    cin >> n >> m;
    for (int i = 0; i < n; i++)
    {
        cin >> q[i];
    }
    while (m--)
    {
        int x;
        cin>>x;
        cout<<left_border(x)<<" "<<right_border(x)<<endl;
    }
    system("pause");
    return 0;
}

3. 方法三(调用函数)

函数解释

binary_search(arr[], arr[]+size, index) 查找某个元素是否出现
lower_bound(arr[], arr[]+size, index) 查找第一个大于或等于某个元素的位置
upper_bound(arr[] , arr[]+size, index) 查找第一个大于某个元素的位置
注解:arr[]:数组首地址,size:数组元素个数,index:需要查找的值
 

#include <bits/stdc++.h>
using namespace std;

const int N=100000;
int n,m; 
int q[N];
int main()
{
    cin >> n >> m;
    for(int i = 0;i < n;i++)
    {
        cin >> q[i];
    }
    while(m--)
    {
        int x;
        cin >> x;
        if(binary_search(q,q+n,x))
        {
            cout << lower_bound(q,q+n,x) - q << " " 
            << upper_bound(q,q+n,x) - q - 1 << endl;
        }else{
            cout << "-1 -1" << endl;
        }
    }
    return 0;
}

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【蓝桥杯EDA设计与开发】资料汇总以及立创EDA及PCB相关技术资料汇总(持续更新)

[18/01/2024]&#xff1a;目前为了准备蓝桥杯做一些资料贴&#xff0c;于是写下这一篇博客。 各种资料均来源于网络以及部分书籍、手册等文档&#xff0c;参考不保证其准确性。 如果在准备蓝桥杯&#xff0c;可与我私信共同学习&#xff01;&#xff01;&#xff01;&#xf…

无尽的石头

题目 import java.util.Scanner;public class Main {public static int func(int res) {int sum 0;while(res!0) {int s res%10;sums;res/10;}return sum;}public static void main(String[] args) {Scanner sc new Scanner(System.in);int t sc.nextInt();sc.nextLine();…

浅谈重组IgG抗体表达-泰克生物

一&#xff0e;IgG抗体简介 IgG作为机体的免疫卫士&#xff0c;主要在机体免疫中起保护作用&#xff0c;对抗大部分的细菌和病毒。IgG是唯一能通过胎盘的免疫球蛋白&#xff0c;IgG能够激活补体系统&#xff0c;参与抗体介导的细胞毒性即ADCC作用&#xff0c;同时参与部分超敏反…

如何免费从 SD 卡恢复已删除的文件?(照片、视频、MP3)

今天我们将告诉您如何免费从格式化的 SD 卡或闪存卡恢复文件。 特别是如果您是一名摄影师、博主或任何处理内容的人&#xff0c;您的 SD 卡上有一些内容&#xff0c;但您不小心删除或格式化了&#xff0c;现在您要向自己道歉。 无需担心&#xff0c;因为今天我们将告诉您如何…

Redis在Windows10中安装和配置

1.首先去下载Redis 这里不给出下载地址&#xff0c;自己可以用去搜索一下地址 下载 下载完成后解压到D盘redis下&#xff0c;本人用的是3.2.100 D:\Redis\Redis-x64-3.2.100 2.解压完成后需要设置环境变量&#xff0c;这里新建一个系统环境变量中path 中添加一个文件所…

MobX 的 Observable Array,如何转换成一个普通的数组

问题描述 访问mobx store里面的数据时打印结果为如下&#xff0c;是一个 MobX 的 Observable Array&#xff0c;而不是一个普通的数组。MobX 使用 Proxy 来实现响应式数据&#xff0c;因此打印的结果为的是 Proxy 对象。可是我需要的是实际的数组数据。 Proxy {0: Proxy, 1: …

电脑怎么定时打开指定文件?两种方法教给你

在电脑中定时打开文件&#xff0c;可以帮助我们节省时间&#xff0c;提高操作效率。那么&#xff0c;电脑怎么定时打开指定文件&#xff1f;下面小编就来教你两种方法。 方法一&#xff1a;利用任务计划程序定时打开文件 在“此电脑”上单击鼠标右键&#xff0c;选择“管理”。…

【Vue】vue项目中Uncaught runtime errors:怎样关闭

vue项目中Uncaught runtime errors:怎样关闭 一、背景描述二、报错原因三、解决方案3.1 只显示错误信息不全屏覆盖3.2 取消全屏覆盖 四、参考资料 一、背景描述 项目本来运行的好好&#xff0c;换了个新的浏览器&#xff0c;新的Chrome浏览器版本号是116.0.5845.97&#xff08…

红队渗透靶机:TOPPO: 1

目录 信息收集 1、arp 2、nmap 3、nikto 4、whatweb 5、dirsearch WEB tips1 tips2 SSH登录 提权 系统信息收集 本地 信息收集 1、arp ┌──(root㉿ru)-[~/kali] └─# arp-scan -l Interface: eth0, type: EN10MB, MAC: 00:0c:29:69:c7:bf, IPv4: 192.168.110…

采集B站up主视频信息

一、网页信息&#xff08;示例网址&#xff1a;https://space.bilibili.com/3493110839511225/video&#xff09;

基于SSM的KTV包厢管理系统(有报告)。Javaee项目,ssm项目。

演示视频&#xff1a; 基于SSM的KTV包厢管理系统&#xff08;有报告&#xff09;。Javaee项目&#xff0c;ssm项目。 项目介绍&#xff1a; 采用M&#xff08;model&#xff09;V&#xff08;view&#xff09;C&#xff08;controller&#xff09;三层体系结构&#xff0c;通过…

【极光系列】springBoot集成elasticsearch

【极光系列】springBoot集成elasticsearch 一.gitee地址 直接下载解压可用 https://gitee.com/shawsongyue/aurora.git 模块&#xff1a;aurora_elasticsearch 二.windows安装elasticsearch tips&#xff1a;注意es客户端版本要与java依赖版本一致&#xff0c;目前使用7.6…

掌握大模型这些优化技术,优雅地进行大模型的训练和推理!

ChatGPT于2022年12月初发布&#xff0c;震惊轰动了全世界&#xff0c;发布后的这段时间里&#xff0c;一系列国内外的大模型训练开源项目接踵而至&#xff0c;例如Alpaca、BOOLM、LLaMA、ChatGLM、DeepSpeedChat、ColossalChat等。不论是学术界还是工业界&#xff0c;都有训练大…

5分钟教会你如何在生产环境debug代码

前言 有时出现的线上bug在测试环境死活都不能复现&#xff0c;靠review代码猜测bug出现的原因&#xff0c;然后盲改代码直接在线上测试明显不靠谱。这时我们就需要在生产环境中debug代码&#xff0c;快速找到bug的原因&#xff0c;然后将锅丢出去。 生产环境的代码一般都是关闭…

Peter算法小课堂—拓扑排序与最小生成树

拓扑排序 讲拓扑排序前&#xff0c;我们要先了解什么是DAG树。所谓DAG树&#xff0c;就是指“有向无环图”。请判断下列图是否是DAG图 第一幅图&#xff0c;它不是DAG图&#xff0c;因为它形成了一个环。第二幅图&#xff0c;它也不是DAG图&#xff0c;因为它没有方向。第三幅…

Red Hat Enterprise Linux 6.10 安装图解

引导和开始安装 选择倒计时结束前&#xff0c;通过键盘上下键选择下图框选项&#xff0c;启动图形化安装过程。需要注意的不同主板默认或者自行配置的固件类型不一致&#xff0c;引导界面有所不同。也就是说使用UEFI和BIOS的安装引导界面是不同的&#xff0c;如图所示。若手动调…

SpringBoot 服务注册IP选择问题

问题 有时候我们明明A\B服务都注册成功了&#xff0c;但是相互之间就是访问不了&#xff0c;这大概率是因为注册时选择IP时网卡选错了&#xff0c;当我们本地电脑有多个网卡时&#xff0c;程序会随机选择一个有IPV4的网卡&#xff0c;然后读取IPv4的地址 比如我的电脑有3个网…

mysql中的联合索引为什么要遵循最佳左前缀法则?

mysql中的联合索引为什么要遵循最佳左前缀法则&#xff1f; 一、什么是联合索引二、联合索引的优化1.常规的写法&#xff08;回表查询&#xff09;2.优化写法&#xff08;索引覆盖&#xff09; 三、 为什么要遵循最佳左前缀法则&#xff1f;1.如下查询语句可以使用到索引&#…

[C#]C# winform部署yolov8目标检测的openvino模型

【官方框架地址】 https://github.com/ultralytics/ultralytics 【openvino介绍】 OpenVINO&#xff08;Open Visual Inference & Neural Network Optimization&#xff09;是由Intel推出的&#xff0c;用于加速深度学习模型推理的工具套件。它旨在提高计算机视觉和深度学…

【LeetCode】数学精选4题

目录 1. 二进制求和&#xff08;简单&#xff09; 2. 两数相加&#xff08;中等&#xff09; 3. 两数相除&#xff08;中等&#xff09; 4. 字符串相乘&#xff08;中等&#xff09; 1. 二进制求和&#xff08;简单&#xff09; 从字符串的右端出发向左做加法&#xff0c;…