【算法 高级数据结构】树状数组:一种高效的数据结构(一)

🚀个人主页:为梦而生~ 关注我一起学习吧!
💡专栏:算法题、 基础算法~赶紧来学算法吧
💡往期推荐
【算法基础 & 数学】快速幂求逆元(逆元、扩展欧几里得定理、小费马定理)
【算法基础】深搜


文章目录

  • 1 引言
    • 1.1 树状数组的概念
    • 1.2 树状数组的应用场景
  • 2 基础知识
    • 2.1 二进制索引的概念和性质
    • 2.2 前缀和的概念和计算
  • 3 树状数组的定义和数学推导
    • 3.1 通俗易懂的解释什么是树状数组※
    • 3.2 树状数组的数学推导※


1 引言

1.1 树状数组的概念

树状数组(Binary Indexed Tree,BIT)是一种数据结构,用于高效地处理数组的动态查询和更新操作。它可以在O(log n)的时间复杂度内完成单点更新和前缀和查询操作。树状数组常用于解决数组频繁更新和查询前缀和的问题,比如求解逆序对、区间和等。

在这里插入图片描述

1.2 树状数组的应用场景

  1. 动态查询问题:树状数组非常适用于需要动态查询某个区间内元素和的场景。
  2. 频繁更新问题:树状数组也适用于频繁更新数组元素的情况。
  3. 逆序对问题:逆序对问题是一个常见问题,即找出数组中所有满足i<ja[i]>a[j](i, j)对。树状数组可以在O(nlogn)的时间复杂度内解决这个问题。

2 基础知识

2.1 二进制索引的概念和性质

二进制索引,也称为树状数组或有限差分数组,是一种特殊的数据结构,用于高效地处理数组中的前缀和查询。它的核心思想是利用二进制表示中的每一位来快速计算前缀和,从而实现高效的查询和更新操作。

在这里插入图片描述

概念

二进制索引的主要概念是基于数组元素的二进制表示来构建索引。具体来说,对于数组中的每个元素,我们可以将其下标转换为二进制形式,并根据二进制位来构建索引。通过维护这些索引,我们可以快速计算数组的前缀和,从而实现高效的查询和更新操作。

性质

  • 前缀和查询的高效性:二进制索引可以在O(log n)的时间复杂度内计算数组的前缀和。这是因为它利用了二进制表示的特性,通过跳跃式地计算不同位上的前缀和,实现了快速查询。
  • 单点更新的高效性:与前缀和查询一样,二进制索引也可以在O(log n)的时间复杂度内完成单点更新操作。当数组中的某个元素发生变化时,只需要更新对应的索引,即可快速反映到前缀和上。
  • 空间效率:二进制索引的空间复杂度与原始数组相同,即O(n)。它不需要额外的存储空间来维护索引结构,因此具有较高的空间效率。

2.2 前缀和的概念和计算

前缀和(Prefix Sum)是一个数组的概念,指的是数组中从第一个元素开始到某个位置元素(包括该位置元素)的总和。前缀和通常用于快速计算某个区间的和,避免了对每个元素进行逐一相加的操作,从而提高计算效率。

计算前缀和的方法很简单,通常是通过迭代数组中的每个元素,并将当前元素与前一个元素的前缀和相加,得到当前元素的前缀和。第一个元素的前缀和就是它本身。

例如,给定一个数组 arr = [1, 2, 3, 4, 5],它的前缀和数组 prefix_sum 可以这样计算:

prefix_sum[0] = arr[0] = 1  
prefix_sum[1] = arr[0] + arr[1] = 1 + 2 = 3  
prefix_sum[2] = arr[0] + arr[1] + arr[2] = 1 + 2 + 3 = 6  
prefix_sum[3] = arr[0] + arr[1] + arr[2] + arr[3] = 1 + 2 + 3 + 4 = 10  
prefix_sum[4] = arr[0] + arr[1] + arr[2] + arr[3] + arr[4] = 1 + 2 + 3 + 4 + 5 = 15

所以,前缀和数组 prefix_sum 为 [1, 3, 6, 10, 15]。


3 树状数组的定义和数学推导

3.1 通俗易懂的解释什么是树状数组※

在这里插入图片描述

对于一个数组,我们通常需要这样的操作:

  1. 修改某个元素的值
  2. 求一段区间的和

如果用朴素的做法,我们通常需要开一个数组,保存下来所有元素,每查询一次,遍历一次数组

但这会使得求和操作的时间复杂度达到 O ( n ) O(n) O(n),但如果数据量和查询次数达到上百万,这样的效率太低了

  • 但有人可能会想到,把数组中的元素两两求和,保存到另一个数组中:
    在这里插入图片描述

这样我们在计算的时候就会节省一半的时间,修改数据的时候也就是多改一个数字而已,但是对于很大的数据量,还是很慢。

  • 那我们可以再将这一层元素两两求和,往上叠加一层,直到只剩一个元素为止:
    在这里插入图片描述

这样即使要求和的数字很多,我们也可以利用这些额外的数组计算出需要的答案(用空间换时间的思想)

例如:要计算前14个数字的和
在这里插入图片描述
只需要计算这样4个数字就行
在这里插入图片描述

即使要计算前一百万个数字的和,我们也只需要进行10~20次加法

这样将查询的时间复杂度降到了 O ( log ⁡ n ) O(\log n) O(logn),效率提升了很多

观察这个数组我们可以发现,数组中的某些数字是不会用到的,大家可以手动模拟一下,所有层的第偶数个数字在计算时都不会被用到,都有更好的方案来替代
在这里插入图片描述

去除掉不会被用到的数字之后,剩下的数字正好是 n n n个,这与数组的长度是一样的

所以,我们可以用一个与原数组长度相同的数组来装下这些数,这个数组就是一颗树状数组,数组中的每一个元素都对应下面的每一个区间,这些区间表示的都是每个对应的区间和
在这里插入图片描述
求和时,我们只需要找到对应的区间,将这些区间相加即可找到答案

修改某个数据时,我们也只需要向上找到包含它的所有区间修改即可

所有查询以及修改元素的操作,都可以在 O ( log ⁡ n ) O(\log n) O(logn)的时间复杂度内完成

3.2 树状数组的数学推导※

对于一个数 x x x,我们可以把它分解成二进制的形式:
2 i k + 2 i k − 1 + 2 i k − 2 + . . . + 2 i 1 2^{i_{k}}+2^{i_{k-1}} + 2^{i_{k-2}} + ... + 2^{i_{1}} 2ik+2ik1+2ik2+...+2i1其中, 2 i k 2^{i_k} 2ik表示 x x x的最高二进制位, 2 i 1 2^{i_{1}} 2i1表示最低二进制位 i k ≥ i k − 1 ≥ . . . ≥ i 1 ( k ≤ log ⁡ x ) i_{k} \geq i_{k-1} \geq ... \geq i_{1} (k \leq \log x) ikik1...i1(klogx)

假设我们要求 1 − x 1-x 1x的和,我们可以把区间分成 k k k个区间

( x − 2 i 1 , x ] (x-2^{i_1},x] (x2i1,x]
( x − 2 i 1 − 2 i 2 , x − 2 i 1 ] (x-2^{i_1}-2^{i_2},x-2^{i_1}] (x2i12i2,x2i1]
. . . ... ...
( 0 , x − 2 i 1 − 2 i 2 − . . . − 2 i k − 1 ] (0,x-2^{i_1}-2^{i_2}-...-2^{i_{k-1}}] (0,x2i12i2...2ik1]

这样我们把 x x x分成了 log ⁡ x \log x logx个区间,如果我们把所有区间的和都预处理出来,最多只需要加 log ⁡ x \log x logx次就可以将区间和算出来

如何预处理这些数呢?

我们看一下这些区间有什么性质:

  • 首先,每个区间都包含 2 i 2^i 2i个数
  • 每个区间 ( L , R ] (L,R] (L,R]的长度一定是 R R R的二进制表示的最后一位 1 1 1所对应的次幂

所以,利用lowbit函数,我们可以把贝格区间简化为 ( R − l o w b i t ( R ) + 1 , R ] (R-lowbit(R)+1,R] (Rlowbit(R)+1,R](该函数的定义如下)

def lowbit(x):return x & -x

于是,我们如果想用数组来记录区间和,可以用c[R]来表示区间和:c[x] = a[x - lowbit(x) + 1, x]

下面来看一下c[x]之间的关系:

在这里插入图片描述

经过这样的数学推导之后,我们得到了与上面介绍中一致的形式

下面来介绍一下如何计算的数学推导

  • 给出x,如何找到x的所有子节点

假设 x > 0 x > 0 x>0,则必然存在最后一位 1 1 1,假设这一位 1 1 1后面有 k k k 0 0 0,我们让 x − 1 x-1 x1,则后面有连续的 k k k 1 1 1,这每个 1 1 1都对应一个儿子,我们找每个儿子只需要每次减去最后一位 1 1 1,一直减 k k k次,直到变成 0 0 0

二进制表示解释如下:

c[x] ~ (x - lowbit(x) + 1, x]
x - 1 ~ ...1000(k个0)
儿子区间1 : (...0111, ...0110]
儿子区间2 : (...0110, ...0100]
儿子区间3 : (...0100, ...0000]
  • 如何通过子节点找父节点?

这个与找儿子结点是相反的,是一个迭代的过程,通常用于修改结点

假设给定一个x,修改完a[x]之后要修改哪些区间和?

假设 p p p是一个父节点,它的二进制表示要满足要找子节点之前的形式(最后一位1后面跟着若干个0),那么它的子节点一定满足那个1变成0,后面跟若干个1,后面是若干个0

我们只需要把上面的过程逆过来就可以了

每次加上一个lowbit(x),就找到直接父节点,然后一直往上加,直到加到那个父节点的位置是1,一共加 log ⁡ x \log x logx次,就可以找到所有父节点

对于一个要修改的a[x],修改操作的代码是:

for(int i = x; i <= n; i += lowbit(i)) tr[i] += c;

要想明白的是:为什么改完x之后,只需要更新tr数组的最多这么logx个位置(结合上面的黑白图)

查询(1~x的区间和)操作的代码(找子区间):

for(int i = x; i; i -= lowbit(x)) res += tr[i];

部分内容及灵感来源:
https://www.bilibili.com/video/BV1ce411u7qP/
https://www.acwing.com/file_system/file/content/whole/index/content/172493/

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

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

相关文章

Python与FPGA——图像锐化

文章目录 前言一、图像锐化二、Python robert锐化三、Python sobel锐化四、Python laplacian锐化五、FPGA sobel锐化总结 前言 在增强图像之前一般会先对图像进行平滑处理以减少或消除噪声&#xff0c;图像的能量主要集中在低频部分&#xff0c;而噪声和图像边缘信息的能量主要…

品牌要把控质量也要管控价格

在品牌发展的道路上&#xff0c;产品质量的把控非常重要&#xff0c;关系到品牌的竞争力&#xff0c;但品牌要长期发展&#xff0c;产品要获得市场足够份额&#xff0c;还需要有稳定的价格体系做支撑&#xff0c;这个价格不是仅凭品牌单方面的定价而定&#xff0c;而是整个渠道…

Oracle定时任务和存储过程

--1.声明定时任务 DECLAREjob NUMBER; BIGIN dbms_job.sumit(job, --任务ID,系统定义的test_prcedure(19)&#xff0c;--调用存储过程&#xff1f;to_date(20240305 02:00&#xff0c;yyyymmdd hh24:mi) --任务开始时间sysdate1/(24*60) --任务执行周期 [每分钟执行…

商业前端TS开发自动化工具

本期作者 一、背景 商业侧的业务比较复杂&#xff0c;B端项目中含有大量常量类的类型判断&#xff0c;且因历史原因&#xff0c;很多常量值前端无法直接知其含义&#xff0c;这既不利于新人的上手&#xff0c;也不利于项目的维护。 在开发协作上&#xff0c;前后端的API沟通&a…

什么是工业边缘网关?工业边缘网关有什么作用?

在数字化和智能化的浪潮下&#xff0c;工业领域正迎来前所未有的变革。其中&#xff0c;工业边缘网关作为这场变革中的重要角色&#xff0c;正逐渐受到人们的关注。那么&#xff0c;什么是工业边缘网关&#xff1f;它如何在工业数字化中发挥作用&#xff1f;今天&#xff0c;就…

Wireshark——获取捕获流量的前N个数据包

1、问题 使用Wireshark捕获了大量的消息&#xff0c;但是只想要前面一部分。 2、方法 使用Wireshark捕获了近18w条消息&#xff0c;但只需要前5w条。 选择文件&#xff0c;导出特定分组。 输入需要保存的消息范围。如&#xff1a;1-50000。 保存即可。

环链表寻找交点

目录 1.题目描述和出处 2.分析 3.代码 1.题目描述和出处 LCR 022. 环形链表 II - 力扣&#xff08;LeetCode&#xff09; 描述很简单&#xff0c;寻找交点&#xff0c;找到则返回交点&#xff0c;找不到返回空。 2.分析 如图&#xff1a;&#xff08;b表示环的长度&#…

springboot3.x集成nacos踩坑,并实现多环境配置

一、nacos安装部署 springboot3.x集成Nacos首先需要将Nacos从1.x升级到2.x&#xff0c;建议直接安装2.x版本&#xff0c;手动将1.x的配置信息迁移到2.x中&#xff0c;先并行一段时间&#xff0c;待全部迁移完成稳定运行之后再停掉1.x&#xff0c;升级和安装、操作请查看官方文…

DailyNotes个人笔记管理工具

DailyNotes 是记录笔记和跟踪任务的应用程序&#xff0c;使用markdown进行编辑 部署 下载镜像 docker pull m0ngr31/dailynotes创建目录并授权 mkdir -p /data/dailynotes/config_dir chmod -R 777 /data/dailynotes启动容器 docker run -d --restart always --name mynot…

Java中的数据压缩和存储技术:Zip、GZip与Brotli

第1章&#xff1a;引言 大家好&#xff0c;我是小黑&#xff0c;作为一名Java程序员&#xff0c;在业务开发中&#xff0c;常常面临着一个问题&#xff1a;如何高效地处理和传输这些庞大的数据呢&#xff1f;答案就在于数据压缩技术。数据压缩&#xff0c;简而言之&#xff0c…

SpringBoot+Ajax+redis实现隐藏重要接口地址

&#x1f3e1;浩泽学编程&#xff1a;个人主页 &#x1f525; 推荐专栏&#xff1a;《深入浅出SpringBoot》《java对AI的调用开发》 《RabbitMQ》《Spring》《SpringMVC》《项目实战》 &#x1f6f8;学无止境&#xff0c;不骄不躁&#xff0c;知行合一 文章目录 …

九型人格测试,8号领袖型人格的职业分析

8号人格&#xff0c;也叫领袖型人格&#xff0c;在九型人格中间&#xff0c;是一种天生领导的存在。他们生性开朗&#xff0c;能够和其他人建立良好的关系&#xff0c;为人不拘小节&#xff0c;遇强则强&#xff0c;坚守心中的理想和正义。不喜欢被人控制&#xff0c;喜欢自己当…

Java并发-并发模型

可以使用不同的并发模型来实现并发系统。一并发模型指定的系统协作线程如何完成他们给予的任务。不同的并发模型以不同的方式拆分任务&#xff0c;线程可以以不同的方式进行通信和协作。本并发模型教程将更深入地介绍撰写本文时&#xff08;2015年至2019年&#xff09;使用的最…

大模型时代,华为与中软国际携手“打通AI落地应用最后一公里”

文 | 智能相对论 作者 | 叶远风 大模型驱动千行百业智能化变革已经成为广泛共识&#xff0c;下一步的问题是&#xff0c;企业要如何更好地推进&#xff1f; 近日&#xff0c;“2024中关村论坛系列活动——第二届北京人工智能产业创新发展大会”在北京国家会议中心成功举办&a…

yudao-cloud 学习笔记

前端代码 浏览器打开 https://cloud.iocoder.cn/intro/ F12 执行代码 var aaa $(".sidebar-group-items").find("a"); var ll[]; var tt[]; for(var i0;i<aaa.length;i ){ ll.push("https://doc.iocoder.cn" $(aaa[i]).attr("href&quo…

Hi3516DV500+SC2210 AIISP 黑光相机

1. Hi3516DV500 Hi3516DV500是一颗面向行业市场推出的高清智能网络摄像头SoC。该芯片最高支持2路sensor输入&#xff0c;支持最高5M30fps的ISP图像处理能力&#xff0c;支持2F WDR、多级降噪、六轴防抖、多光谱融合等多种传统图像增强和处理算法&#xff0c;支持通过AI算法对输…

第11周,第三期技术动态

大家好&#xff0c;才是真的好。 真没想到&#xff0c;本周是今年第十一周&#xff0c;2024年还有不到三百天就结束了。 今天周五&#xff0c;我们继续介绍与Domino相关产品新闻&#xff0c;以及互联网或其他IT行业动态等。 一、在Windows 10和Windows 11上运行Domino和Trav…

案例研究|辛格林电梯借助DataEase实现数据整合与智能展示

辛格林电梯&#xff08;SIGLEN&#xff09;于2012年创立&#xff0c;是电梯领域的领军品牌之一。该公司总部位于广东佛山&#xff0c;是全国首批获得A1级电梯制造资质的企业&#xff0c;拥有省级工程技术研究中心。辛格林电梯专注于研发和生产高品质电梯产品&#xff0c;涵盖别…

一个用libcurl多线程下载断言错误问题的排查

某数据下载程序&#xff0c;相同版本的代码&#xff0c;在64位系统中运行正常&#xff0c;但在32位系统中概率性出现断言错误。一旦出现&#xff0c;程序无法正常继续&#xff0c;即使重启亦不行。从年前会上领导提出要追到根&#xff0c;跟到底&#xff0c;到年后的今天&#…

通过统一规划和团队整合,提升企业财务洞察

在当今快节奏的商业环境中&#xff0c;企业财务职能部门更应该采取更迅速的行动来适应这个社会。大部分企业期待更高效的战略决策&#xff0c;尤其是面临海量数据信息的堆叠。但是企业领导者应该知道&#xff0c;速度本身并不是最终目标&#xff0c;财务团队必须更快地完成工作…