首页 > 编程语言 >【算法】二分

【算法】二分

时间:2022-08-26 17:57:32浏览次数:63  
标签:二分 begin int 元素 mid bound lower 算法

y总二分模板

y总模板链接

bool check(int x) {/* ... */} // 检查x是否满足某种性质

// 区间[l, r]被划分成[l, mid]和[mid + 1, r]时使用:
int bsearch_1(int l, int r)
{
    while (l < r)
    {
        int mid = l + r >> 1;
        if (check(mid)) r = mid;    // check()判断mid是否满足性质
        else l = mid + 1;
    }
    return l;
}

// 区间[l, r]被划分成[l, mid - 1]和[mid, r]时使用:
int bsearch_2(int l, int r)
{
    while (l < r)
    {
        int mid = l + r + 1 >> 1;
        if (check(mid)) l = mid;
        else r = mid - 1;
    }
    return l;
}

经典练习

789.数的范围

给定一个按照升序排列的长度为 nn 的整数数组,以及 qq 个查询。

对于每个查询,返回一个元素 kk 的起始位置和终止位置(位置从 00 开始计数)。

如果数组中不存在该元素,则返回 -1 -1

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

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

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

输入样例

6 3
1 2 2 3 3 4
3
4
5

输出样例

3 4
5 5
-1 -1

代码:

#include <iostream>
using namespace std;

const int N = 100010;
int n, q;
int a[N];

int main() {
    cin >> n >> q;
    for (int i = 0; i < n; i++) cin >> a[i];
    
    for (int i = 0; i < q; i++) {
        int k;
        cin >> k;
        // 先找最左边
        int l = 0, r = n - 1;
        while (l < r) {
            int mid = (l + r) >> 1;
            if (a[mid] >= k) r = mid;
            else l = mid + 1;
        }
        // 未找到
        if (a[l] != k) cout << "-1 -1" <<endl;
        else {
            int left = l;
            // 找最右边
            l = 0, r = n - 1;
            while (l < r) {
                int mid = (l + r + 1) >> 1;
                if (a[mid] <= k) l = mid;
                else r = mid - 1;
            }
            cout << left << " " << r << endl;
        }
    }
    return 0;
}

力扣题解区总结

拓展

在C++中的STL标准库中提供了 lower_bound 函数,定义在 <algorithm> 头文件中。

lower_bound() 函数用于在指定区域内查找不小于目标值的第一个元素。也就是说,使用该函数在指定范围内查找某个目标值时,最终查找到的不一定是和目标值相等的元素,还可能是比目标值大的元素。

可以利用它来检索区间内某一个数的位置(可以理解为数组的下标)。

例如:

vector<int> v = {1, 2, 5, 7, 10};
int idx1 = lower_bound(v.begin(), v.end(), 5) - v.begin();
int idx2 = lower_bound(v.begin(), v.end(), 8) - v.begin();
int idx3 = lower_bound(v.begin(), v.end(), 12) - v.begin();
cout << "idx1: " << idx1 << endl;
cout << "idx2: " << idx2 << endl;
cout << "idx3: " << idx3 << endl;

输出为:

idx1: 2
idx2: 4
idx3: 5

由上可看出几点:

  1. 该函数的返回值是一个迭代器,若想得到在容器中的位置(下标)还需减去其begin;
  2. 当想查找元素在区间内时,若有该元素,能返回其位置;否则返回第一个比它大的数的位置;
  3. 当元素不在区间内时,返回的迭代器为end,其减去begin后得到的为容器大小。

标签:二分,begin,int,元素,mid,bound,lower,算法
From: https://www.cnblogs.com/iliuyx/p/16628465.html

相关文章

  • java质数算法
    importjava.util.ArrayList;importjava.util.Iterator;importjava.util.List;importjava.stream.Collectors;importjava.stream.Stream;publicclassMain{publ......
  • Kruskal和Prim算法详解
    最小生成树概念(转载)假设一个国家有一些城市,这些城市可以互相连接起来,假设每两个城市之间的道路有很多条,那么一定存在这样的情况,可以用最少的路程连接各个城市。......
  • #前端算法救赎系列#LeetCode03.无重复字符的最长子串
    3.无重复字符的最长子串给定一个字符串s,请你找出其中不含有重复字符的最长子串的长度。示例1:输入:s="abcabcbb"输出:3解释:因为无重复字符的最长子串是......
  • [算法]区间归并
    问题分析有的时候,会遇到给定一系列的区间,求交集or并集,或者合并的题.这些题的解题方式比较通用个,做一个总结.会用到集合和归并排序的相关知识.两个区间的关系有六种......
  • 2022“杭电杯”中国大学生算法设计超级联赛(10) 题解
    C.WavyTree发现修改次数和相邻两数的相对大小有关,所以可先求出差分数组。分两种情况考虑:①奇数位置为波峰②偶数位置为波峰。以情况①为例,若奇数位置差分后值小......
  • 497. 非重叠矩形中的随机点 ( presum+二分)
     难度中等140收藏分享切换为英文接收动态反馈给定一个由非重叠的轴对齐矩形的数组 rects ,其中 rects[i]=[ai,bi,xi,yi] 表示 (ai,bi) 是第 i 个矩形......
  • 数据结构与算法分析--C语言描述 pdf
    高清扫描版下载链接:https://pan.baidu.com/s/1BGsOOAOqXE9j509OFtkjXA点击这里获取提取码书中详细介绍了当前流行的论题和新的变化,讨论了算法设计技巧,并在研究算法的性能......
  • 数据结构与算法分析 Java版 pdf
    高清扫描版下载链接:https://pan.baidu.com/s/1vDsOy1E0kHizahB6hIg2tA点击这里获取提取码本书以Java语言为基础,讨论了数据结构的线性结构和非线性结构及其实现,全书以Java......
  • 算法学习--广度优先搜索和深度优先搜索
    广度优先搜索BFS一、相关概念1.图的遍历:从图中某一顶点出发,按照某种搜索方法沿着图中的边对图中的所有节点访问一次且仅访问一次二、算法流程首先访问起始顶点v;......
  • vue 3.0 国密sm2算法加密解密文件流
     针对文件流加密需要考虑性能问题,所以选择部分文件字节加密,破坏文件内容,达到用户不能随意下载打开文件 ts文件:import{sm2}from'sm-crypto';import{Buffer}......