0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

一种比线段树还高效的区间算法

算法与数据结构 来源:小K算法 作者:小K算法 2022-04-11 09:36 次阅读

01 故事起源

有N个数排列成一排,给定一个区间,如何快速找出区间内最大的数是多少呢?

34f9dfbe-b7a6-11ec-aa7f-dac502259ad0.jpg

02 分析

首先想到的自然是从区间头开始,依次遍历完区间内的元素,这样就可以找出结果了。但这个复杂度是O(n),肯定不是我们想要的。

350a9016-b7a6-11ec-aa7f-dac502259ad0.jpg

再来分析一下有什么特点呢?

这些数不会更改,所以每个区间的结果是不会变的,是否可以把所有的区间结果先计算出来?

3524ef60-b7a6-11ec-aa7f-dac502259ad0.jpg

如果数据规模很小确实可以,一旦数据过大肯定就不行了,因为时间和空间都是O(n^2)。

353e0d1a-b7a6-11ec-aa7f-dac502259ad0.jpg

再考虑一下,区间的最值是有很强的传递关系,这就引导我们可以把大问题化为小问题。

355903ea-b7a6-11ec-aa7f-dac502259ad0.jpg

很显然,这就是一个标准的线段树模型,不过今天我们再换一个更加高效的算法,稀疏表。 03 稀疏表稀疏表的思想就是提前预处理数据,所以主要针对数据不变的情况,而线段树更加灵活,可以动态维护数据的变化。

首先还是将区间划分成很多的小区间。那如何划分更合理?

第2章节中,我们枚举了所有的区间情况,可以看出其实有很多重复的情况,比如下面[0,3]其实可以通过[0,1]和[2,3]组合出来。

356cb1c4-b7a6-11ec-aa7f-dac502259ad0.jpg

可以根据长度划分区间。

设数组为a[i],f[i][j]表示区间[i,j]的最大值。

则长度为1的区间总共有n个,f[i][i]=a[i]。

3584108a-b7a6-11ec-aa7f-dac502259ad0.jpg

长度为2的区间总共有n-1个。

358f1458-b7a6-11ec-aa7f-dac502259ad0.jpg

因为之前已经求出了长度为1的区间的最大值,所以区间长度为2的最大值可以通过区间长度为1的结果直接推出来。

359f34aa-b7a6-11ec-aa7f-dac502259ad0.jpg

接下来就考虑长度为3的区间了吗?

其实并不是,因为前面已经有了长度为1和2的,所以可以组合出长度为3和4的。

35ae665a-b7a6-11ec-aa7f-dac502259ad0.jpg

那就直接考虑长度为5的吗?

如果考虑为5的,那你怎么计算呢,前面的也推不出长度为5的结果啊,至少得有3个区间才能推出来

35c94380-b7a6-11ec-aa7f-dac502259ad0.jpg

所以接下来考虑长度为4的区间才是正解,总共有n-3个。

35dd169e-b7a6-11ec-aa7f-dac502259ad0.jpg

再接下来自然就是考虑长度为8的区间了,总共有n-7个。

但这里有个很明显的问题,就是我们的数组f[i,j]定义的不合理,因为里面很多的小区间没有用上,比如长度为3,5,6,7等,所以需要重新定义。 04 状态压缩可以将第二维用于表示区间长度,第一维表示区间起点,对第二维就可以进行状态压缩。

设f[i,j]表示从i开始,长度为2^j的区间的最大值,即区间[i,i+2^j-1]。

35f43f5e-b7a6-11ec-aa7f-dac502259ad0.jpg

则长度为2^j的区间就可以通过左右2个长度为2^(j-1)的区间推出结果。时间和空间的复杂度都为O(nlogn)。

3609f2ea-b7a6-11ec-aa7f-dac502259ad0.jpg

05 区间分解

那查询结果的时候要怎么处理呢,我们只计算了长度为2^j的区间,并没有计算长度为3、5、7等区间的结果。

所以这个处理和线段树的思想也类似,需要进行区间分解。不过线段树可能分解成很多个区间,而稀疏表只需要分解成2个区间就可以了。

对于任意区间[a,b],长度为b-a+1,总可以找到2个长度为2^j的区间,这2个区间组合起来可以完全覆盖[a,b],其中j的值为log(b-a+1)。

左边的区间左端点从a开始,长度为2^j,即区间[a,a+2^j-1]。右边的区间右端点从b开始,长度为2^j,即区间[b-2^j+1,b]。

则区间[a,b]的最大值就是这两个区间中更大的那个,即max(f[a,j],f[b-2^j+1,j])。

36223a6c-b7a6-11ec-aa7f-dac502259ad0.jpg

06 代码实现

代码实现了最大值和最小值的获取。

6.1变量定义

int high[50000][17], low[50000][17], n, q;

6.1预处理

void solve() {

// 枚举区间长度,2^j《=n

for (int j = 1; (1 《《 j) 《= n; ++j) {

// 枚举左端点i,右端点i+2^j-1《=n-1

for (int i = 0; i + (1 《《 j) 《= n; ++i) {

high[i][j] = max(high[i][j - 1], high[i + (1 《《 (j - 1))][j - 1]);

low[i][j] = min(low[i][j - 1], low[i + (1 《《 (j - 1))][j - 1]);

}

} }

6.1main函数

int main() {

cin 》》 n 》》 q;

for (int i = 0; i 《 n; ++i) {

cin 》》 high[i][0];

low[i][0] = high[i][0];

}

solve();

for (int i = 0; i 《 q; ++i) {

int a, b;

cin 》》 a 》》 b;

a--;

b--;

int j = (int) (log(b - a + 1.0) / log(2.0));

int minHeight = min(low[a][j], low[b - (1 《《 j) + 1][j]);

int maxHeight = max(high[a][j], high[b - (1 《《 j) + 1][j]);

cout 《《 maxHeight - minHeight 《《 endl;

}

return 0; }

07 总结

对于数据不变的情况,可以用稀疏表预处理,这种属于离线算法。如果要动态维护变化,动态查询,那就得用在线算法,比如线段树。但稀疏表的效率确实高,有状态压缩和动态规划的思想,值得深入研究学习。

--- EOF ---

审核编辑 :李倩

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 算法
    +关注

    关注

    23

    文章

    4612

    浏览量

    92927
  • 函数
    +关注

    关注

    3

    文章

    4332

    浏览量

    62641

原文标题:一种比线段树还高效的区间算法

文章出处:【微信号:TheAlgorithm,微信公众号:算法与数据结构】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    ADS1292测量ECG,三个导联测量,测得的心电信号波形,对多数人的测量结果都是T波R波还高而且很宽,为什么?

    使用TI官方方案ADS1292测量ECG,三个导联测量,测得的心电信号波形,对多数人的测量结果都是T波R波还高而且很宽,只有对少数人才正常,是什么原因?
    发表于 12-24 07:55

    一种新型高效率的服务器电源系统

    一种新型高效率的服务器电源系统
    发表于 12-19 16:45 1次下载

    一种混合颜料光谱分区间识别方法

    古代彩绘颜料的分析是科技考古与文物保护研究的重要内容,高光谱是近年来发展迅速的新兴技术,在物质识别上具有广泛应用,提出一种基于高光谱分区间的混合颜料识别方法。 一种混合颜料光谱分区间
    的头像 发表于 12-02 16:22 85次阅读
    <b class='flag-5'>一种</b>混合颜料光谱分<b class='flag-5'>区间</b>识别方法

    【「从算法到电路—数字芯片算法的电路实现」阅读体验】+本介绍基础硬件算法模块实现的好书

    看下本书内容简介,然后再浏览下各个章节的内容。 从简介来看,本书也是关注最基础,最常用的那部分算法的电路实现,比较贴合工程实践,适合无基础或者有定基础的线工程人员阅读。内容选择是贴合实践
    发表于 11-20 13:42

    华纳云:Chord算法如何管理节点间的联系?

    Chord算法一种分布式哈希表(DHT)协议,它通过构建个环状结构来管理节点间的联系。以下是Chord算法如何管理节点间联系的具体方式: 环状结构: Chord
    发表于 11-08 16:03

    一种基于深度学习的二维拉曼光谱算法

    近日,天津大学精密仪器与光电子工程学院的光子芯片实验室提出了一种基于深度学习的二维拉曼光谱算法,成果以“Rapid and accurate bacteria identification
    的头像 发表于 11-07 09:08 230次阅读
    <b class='flag-5'>一种</b>基于深度学习的二维拉曼光谱<b class='flag-5'>算法</b>

    一种简单高效配置FPGA的方法

    本文描述了一种简单高效配置FPGA的方法,该方法利用微处理器从串行外围接口(SPI)闪存配置FPGA设备。这种方法减少了硬件组件、板空间和成本。
    的头像 发表于 10-24 14:57 621次阅读
    <b class='flag-5'>一种</b>简单<b class='flag-5'>高效</b>配置FPGA的方法

    Huffman压缩算法概述和详细流程

    Huffman压缩算法一种基于字符出现频率的编码算法,通过构建Huffman,将出现频率高的字符用短编码表示,出现频率低的字符用长编码表示,从而实现对数据的压缩。
    的头像 发表于 10-21 13:48 278次阅读

    什么是默克尔(Merkle Tree)?如何计算默克尔根?

    01 默克尔的概念 默克尔(Merkle Tree)是一种特殊的二叉,它的每个节点都存储了个数据块的哈希值。哈希值是
    的头像 发表于 09-30 18:22 918次阅读
    什么是默克尔<b class='flag-5'>树</b>(Merkle Tree)?如何计算默克尔根?

    高效精准,电池自动贴面垫机助力锂电生产 斯特自动化

    斯特自动化自动贴面垫机是一种高效、精准的自动化生产设备,广泛应用于多个领域,特别是在锂电池生产、家具制造、建筑装饰等行业中发挥着重要作用。以下是对自动贴面垫机的详细介绍:
    的头像 发表于 07-25 09:56 278次阅读

    rup是一种什么模型

    RUP(Rational Unified Process,统建模语言)是一种软件开发过程模型,它是一种迭代和增量的软件开发方法。RUP是由Rational Software公司(现为IBM的
    的头像 发表于 07-09 10:13 1276次阅读

    基于助听器开发的一种高效的语音增强神经网络

    受限的微控制器单元(microcontroller units,MCU)上,内存和计算能力有限。在这项工作中,我们使用模型压缩技术来弥补这差距。我们在HW上对RNN施加约束,并描述了一种方法来满足它们
    发表于 06-07 11:29

    请问什么原因导致电流刚关闭e-CAMView软件的时候还高

    串口打印EnterSpendMode Status = 0x0、唤醒原因 = 0x8 ,这时候电流约80mA左右,请问什么原因导致电流刚关闭e-CAMView软件的时候还高? 按道理应该小于30ma。怎么能做到进入SuspendMode模式后电流最低?
    发表于 06-03 07:18

    锂电池般的能量是多少?影响锂电池能量的因素

    锂电池作为一种高效的电化学储能设备,其能量是衡量其性能的关键指标之
    的头像 发表于 04-25 17:03 4413次阅读

    一种高效1.5V/4.2V的LED驱动器电路

    本文介绍了一种高效的 1.5 V 至 4.2 V LED驱动器电路,可与标准锂离子电池起使用,以增强照明、延长备用电池和延长电池寿命。
    的头像 发表于 02-25 14:19 1192次阅读
    <b class='flag-5'>一种</b><b class='flag-5'>高效</b>1.5V/4.2V的LED驱动器电路