【Hello Algorithm】最大线段重合及加强堆

这篇具有很好参考价值的文章主要介绍了【Hello Algorithm】最大线段重合及加强堆。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

本篇博客简介:介绍加强堆

计算时间复杂度的技巧

一般来说 我们在刷算法的时候都要求C/C++语言在1到2s之内完成 java这种语言在2到4秒之内完成

而与之对应的指令条数就是 十的八次方 左右 不会超过一个数量级

所以说根据上面的结论 我们就能够反推题目所需要的时间复杂度

比如说一个数组的大小不超过 十的三次方 我们使用N平方的算法肯定能过

但是如果一个数组的大小不超过 十的六次方 我们就要考虑使用时间复杂度为N 或者是N*LogN的算法了

最大线段重合问题

题目描述如下

每一个线段都有start和end两个数据项,表示这条线段在X轴上从start位置开始到end位置结束。
给定一批线段,求所有重合区域中最多重合了几个线段,首尾相接的线段不算重合。
例如:线段[1,2]和线段[2.3]不重合。
线段[1,3]和线段[2,3]重合

我们下面先讲解题的具体方法 之后再说为什么要这么做

具体方法为:

  1. 我们将所有的线段 按照起始位置从小到大的顺序排序
  2. 我们设置一个小根堆
  3. 从第一个线段开始遍历 首先看线段的起始位置值是多少
  4. 将线段起始位置的值和小根堆里面的数进行比较并弹出所有小于等于该值的数字(没有或空就不弹)
  5. 将第一个线段的结束位置的值加入到小根堆当中
  6. 此时小根堆里面有几个数 就是该线段的答案
  7. 之后重复步骤 3~6
  8. 最后我们会得到一个最大值 该最大值就是我们的答案

下面是解释

我们求的最大值得含义是什么

因为我们再第一步将所有得线段按照起始位置从小到大的顺序排好序了

所以说 起始位置一定是在不断变大得(也有可能不变)

因此 我们只要记录每条线段末尾位置的值并且按照从小到大的顺序排序 就能够计算出以当前线段起点为起始位置的情况下穿过当前线段的线段有多少条

于是我们只要计算出每条线段起始位置穿过线段的最大条数之后比较取最大值就能够得到最后的答案了

为什么只要计算出每条线段起始位置穿过线段的最大条数就能够得出最后的答案

同学们可以在笔记上尝试画出任意条线段 找出它们的重合最多的区域之后观察

我们一定能发现 重合区域的起始位置一定是某条线段的起点

于是乎 我们只要计算出以每条线段为起始位置的重合区域最大值一定能够计算出最后的答案

起始位置相同 终止位置不同的线段排序会影响最终结果吗?

不会影响 因为这些线段的起始位置都相同 所以说不会影响小根堆里面的输出弹出 所以说不会影响到最终结果

题目地址及代码

此题可在牛客网上刷 线段重合

代码如下 起始只要理解了思路 代码并不难写

#include <iostream>
using namespace std;
#include <queue>
#include <vector>
#include <algorithm>
bool Less(const pair<int , int>& kv1 , const pair<int , int>& kv2)
{
    return kv1.first < kv2.first;
}


int main() 
{
    // num of section
    int count = 0;
    cin >> count;

    // receive section
    vector<pair<int , int>> v;
    int first = 0;
    int second = 0;
    while(count--)
    {
        cin >> first >> second;
        v.push_back(make_pair(first,second));
    }

    sort(v.begin() , v.end() , Less);
    int max = 0;
    priority_queue<int , vector<int> , greater<int>> pq;
    for (auto x: v)
    {
        while( (!pq.empty()) && pq.top() <= x.first)
        {
            pq.pop();
        }

        pq.push(x.second);
        max = max > pq.size()? max : pq.size();
    }

    cout << max << endl;
 }

加强堆

我们目前在C++中使用的一个 优先级队列 只是一个简单的堆模型

他给我们暴露出来的接口只能够让我们入堆和出堆 处理不了一些较为复杂的场景

比如说我们将堆中的一个元素值变大或者变小

  • 第一 当前的堆无法支持我们上面说的变大变小操作
  • 第二 修改之后堆无法自动恢复成一个新的堆

要想完成上面我们说的功能 我们的堆就必须要有一个反向索引表

什么是反向索引表

反向索引表是一张哈希表

我们的堆本质上是一个数组 但是我们每次加入一个新的元素之后我们就不能得知该元素的位置在数组的什么下标了

如果我们加上一个哈希表 通过这个哈希表 我们就能直接从这张表中找到元素对应的下标 那么这张哈希表就是我们堆对应的反向索引表

为什么堆不给我们提供反向索引表

因为在实际的引用场景中 我们使用堆并没有要用到反向索引表的场景 而如果我们添加了反向索引表 这实际上是一个非常耗费内存的行为

因此 在给我们使用的标准库中并没有添加反向索引表

如何做

我们前面说了 加强堆和堆之间只差了一个反向索引表

所以说我们只需要将堆的代码复制过来 并且给它的成员加上一个反向索引表

在需要改变下标的地方都修改下反向索引表即可

最后给加强堆加上一个接口 让其可以通过反向索引表修改堆内元素的大小(当然修改完也要记得调整位置)文章来源地址https://www.toymoban.com/news/detail-679989.html

到了这里,关于【Hello Algorithm】最大线段重合及加强堆的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【数据结构和算法】最大连续1的个数 III

    Java基础合集 数据结构与算法合集 设计模式合集 多线程合集 分布式合集 ES合集 其他系列文章导航 文章目录 前言 一、题目描述 二、题解 2.1 方法一:滑动窗口  2.2 滑动窗口解题模板 三、代码 3.1 方法一:滑动窗口 四、复杂度分析 4.1 方法一:滑动窗口 这是力扣的 1004 题,

    2024年02月04日
    浏览(43)
  • 【算法与数据结构】654、LeetCode最大二叉树

    所有的LeetCode题解索引,可以看这篇文章——【算法和数据结构】LeetCode题解。    思路分析 :【算法与数据结构】106、LeetCode从中序与后序遍历序列构造二叉树这两道题有些类似,相关代码可以互相参考,本题明示了要用递归来做,那么递归三要素不可缺少: 输入参数和返

    2024年02月09日
    浏览(44)
  • 【高级数据结构】线段树

    目录 树状数组1(单点修改,区间查询) 树状数组2(区间修改,单点查询) 线段树1(区间修改,区间查询) 代码源线段树1(查询最小值出现次数)  代码源线段树2(最大字段和) 树状数组1(单点修改,区间查询) 题目链接:  https://www.luogu.com.cn/problem/P3374 代码: 树状

    2024年02月15日
    浏览(39)
  • 数据结构与算法之堆: Leetcode 215. 数组中的第K个最大元素 (Typescript版)

    数组中的第K个最大元素 https://leetcode.cn/problems/kth-largest-element-in-an-array/ 描述 给定整数数组 nums 和整数 k,请返回数组中第 k 个最大的元素。 请注意,你需要找的是数组排序后的第 k 个最大的元素,而不是第 k 个不同的元素。 你必须设计并实现时间复杂度为 O(n) 的算法解决此

    2024年02月07日
    浏览(48)
  • 数据结构和算法-B树(B树的查找 B树的最大高度和最小高度)

    进一步对范围划分,处于不同划分进入不同子树 四个数做划分,此时有五个区间 此时一个节点对应多个,如果叶子节点依然没有对应的,那么即查找失败,然后看看在叶子节点的的哪个区间 此时每个节点可以只有一个,也可以有多个,其对应

    2024年02月03日
    浏览(26)
  • 读《大话数据结构》溢彩加强版

    源代码: C:迅雷下载202107281602349133559e95a4689eeb92f380f4ab220210729976aaa-ef7a-11eb-aba5-00163e0a088c PPT: C:迅雷下载202107281602349133559e95a4689eeb92f380f4ab2202009942a5ce8-fe34-11ea-a6a1-00163e0396a1 参考文献: C:迅雷下载202107281602349133559e95a4689eeb92f380f4ab2202009c53b3bcc-fe34-11ea-97a4-00163e0a088c 2.5 算法的

    2024年02月15日
    浏览(31)
  • Java手写最大流算法应用拓展案例

    最大流算法是图论中的经典算法,用于解决网络流问题。它的应用非常广泛,可以用于解决许多实际问题,如网络优化、流量分配等。本文将介绍最大流算法的三个拓展应用案例,并给出完整的代码实现。 在某个网络中,存在多个节点和连接这些节点的边。每条边都有一个容

    2024年02月07日
    浏览(49)
  • 【算法】树状数组和线段树

    O ( l o g n ) O(logn) O ( l o g n ) :单点修改、区间查询 与前缀和的区别: 前缀和是离线的,每次动态修改原数组某个元素,都需要重新求一遍前缀和,因此单点修改是 O ( n ) O(n) O ( n ) 的,区间查询则是 O ( 1 ) O(1) O ( 1 ) 树状数组是在线的,单点修改和区间查询都是 O ( l o g n ) O(

    2024年02月19日
    浏览(46)
  • 贪心算法(Greedy Algorithm)

    贪心算法(Greedy Algorithm)是一种解决优化问题的算法策略。在贪心算法中,每一步都会选择当前情况下最优的选择,而不考虑未来的后果。 贪心算法的基本思想是通过局部最优选择达到全局最优。它并不保证一定能得到全局最优解,但在某些情况下可以得到近似最优解或者

    2024年02月09日
    浏览(39)
  • 算法| Java的int类型最大值为什么是21亿多?

    本文主要介绍在 Java 中,为什么 int 类型的最大值为 2147483647 。 我们都知道在 Java 中, int 的长度为32位。 理论上,用二进制表示,32位每一位都是1的话,那么这个数是多少呢? 我们来计算一下,第0位可以用20^00表示,第1位可以用21^11表示,第31位可以用231表示,那么32位二进

    2024年02月04日
    浏览(45)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包