数据结构-IndexTree结构解析(一)

1.IndexTree

        IndexTree解决的问题是什么呢?可以从求前缀和入手这个问题。

1.1前缀和数组

        简单封装一个前缀和数组:

package com.xinghai.arr;import java.util.Arrays;/*** 前缀和数组*/
public class PrefixSumArr {// 存储前缀和数据private int[] prefixSumArr;// 存储前缀和数组的长度private final int N;// 构造前缀和public PrefixSumArr(int[] origin) {N = origin.length;prefixSumArr = new int[N];for (int index = 0; index < origin.length; index++) {for (int idx = 0; idx <= index; idx++) {prefixSumArr[index] += origin[idx];}}}// 获取范围求和数据public int getSum(int left, int right) {if (left < 0 || right >= N) {throw new ArrayIndexOutOfBoundsException("索引越界!!!");}if (left > right) {throw new RuntimeException("无效索引");}return prefixSumArr[right] - (left == 0 ? 0 : prefixSumArr[left - 1]);}public int getSum(int right) {return getSum(0, right);}// 操作前缀和数据// 获取前缀和数组中index位置的数据public int get(int index) {return prefixSumArr[index];}// 为前缀和数组中index位置设置对应数据public void set(int index, int value) {if (index >= N || index < 0) {throw new ArrayIndexOutOfBoundsException("索引越界!!!");}// 获取原来索引对应的数据int rawData = prefixSumArr[index] - ((index > 0) ? prefixSumArr[index - 1] : 0);for (int idx = index; idx < N; idx++) {prefixSumArr[idx] += (value - rawData);}}// 为前缀和数组中index位置的数据增加一定值public void add(int index, int value) {if (index >= N || index < 0) {throw new ArrayIndexOutOfBoundsException("索引越界!!!");}for (int idx = index; idx < N; idx++) {prefixSumArr[idx] += value;}}// 打印前缀和数public void printPrefixSumArr() {System.out.println(Arrays.toString(prefixSumArr));}}

        分析前缀和数组的时间复杂度。

        前缀和数组操作的复杂度主要是分析前缀和数组中的set和add操作。

        假设前缀和数组需要更新index位置的数据,那么需要变动的数据量是(N - index)个,即时间复杂度为O(N - index) => 即为O(N),这个时间复杂度还是比较高的,那么有没有一种方式可以降低前缀和数组的时间复杂度,还能达到前缀和数组的效果吗?

        Index树就达成这种效果的。

        即Index树是为了解决范围求和O(1)的同时,更新数据也能做到O(Log N)的数据结构。

1.2IndexTree是什么?

        IndexTree也是使用数组模拟出的树结构(类似于堆结构,线段树)。

        这种结构主要的特性是可以完成和前缀和数组一样的效果,并且单点数据更新的时间复杂度为O(log N)

2.解析IndexTree数据结构

        掌握IndexTree一定不要尝试去理解发明这个数据结构的人心理路程是怎么样的,因为IndexTree整体设计的比较巧妙,里面的设计很难理解是因为为了发明IndexTree所以诞生这种处理机制,还是因为想到了这种处理机制从而诞生了IndexTree,掌握具体实现有时候比掌握原理其实都重要。

2.1IndexTree的构成

        IndexTree构成用语言描述非常复杂,使用手写画图举例的方式可以研究明白IndexTree的构成:

2.2解析单点更新和前缀求和

        IndexTree的单点更新和前缀求和会让你感觉十分巧妙,但是不会感觉十分难以理解。

        这里我也使用手写的方式呈现出IndexTree是如何构建以及单点更新,范围求和是如何实现的:

        其实看完手写笔记,用一句话总结IndexTree就是:IndexTree每个位置的数据都是从自己当前位置index开始向前累加到(index - index最右边的1 + 1)位置。

        单点更新也是依赖此实现的,将依赖自己的数据都变量(自己加自己右侧的1,一直加到越界为止)

        前缀求和也是依赖IndexTree的特殊结构,先把自己的管的区域(index - index最右侧的1 + 1)- index位置的数据相加,再从index - index最右侧的1开始递归操作,直至越界。

3.详解代码实现

        从代码的角度再去理解IndexTree结构,单点更新,范围求和。

3.1构建IndexTree

        想要更好的构建IndexTree,必须通透了解IndexTree中每个位置如何借助原数组快速构建IndexTree的。

        从手写图中可以总结出:IndexTree中每个位置的累加数据为(index - (index最右侧的1) + 1)- (index)

        记住这个公式,使用代码表示出来就是,从当前位置出发向前累加到index - index最右侧的1 + 1的位置。

        代码实现:

// 索引树 -> 数组封装
private int[] indexTreeArr;
// IndexTree的长度
private int N;// 初始化Index树
public IndexTree(int[] origin) {N = origin.length + 1;indexTreeArr = new int[N];for (int index = 1; index < N; index++) {int idx = index;idx -= ((idx & -idx) - 1);while (idx <= index) {indexTreeArr[index] += origin[idx++ - 1];}}
}

3.2单点更新

        单点更新的核心操作就是从自己开始,一直相加自己最右侧的1,变量位置,更新数据。

// 单点更新
public void add(int index, int value) {if (index < 1 && index >= N) {throw new ArrayIndexOutOfBoundsException("索引越界");}while (index < N) {indexTreeArr[index] += value;index += index & -index;}
}
public void set(int index, int value) {if (index < 1 && index >= N) {throw new ArrayIndexOutOfBoundsException("索引越界");}int oldVal = indexTreeArr[index];while (index < N) {indexTreeArr[index] += (value - oldVal);index += index & -index;}
}

3.3范围求和

        范围求和就是从right出发,将当前IndexTree对应的right的数据(即原始数组中right到right - right最右侧的1 + 1)累加后,再将right设定为right - right最右侧的1,继续反复操作,直到越过left为止。

// 分段求和
public int sum(int left, int right) {if (left < 1 || right < 1 || left >= N || right >= N) {throw new ArrayIndexOutOfBoundsException("索引越界!!!");}if (left > right) {throw new RuntimeException("索引错误!!!");}int sum = 0;while (right >= left) {sum += indexTreeArr[right];right -= right & -right;}left -= 1;while (left > 0) {sum -= indexTreeArr[left];left -= left & -left;}return sum;
}public int sum(int right) {return sum(1, right);
}

4.复杂度分析

        复杂度分析主要分析单点更新和范围求和即可。

        单点更新是O(LogN)的,因为从当前位置出发,只需要改动加上自己最右侧1的数据,相比于前缀和数组提升了一个量级。

        范围求和也是O(LogN)的,因为从当前位置出发,每次位置变动都是将自己最右侧的1抹去,相比于前缀和数组提升了一个量级。

5.结语

        下一步更新IndexTree在二维数组中的妙用,你的点赞就是我更新的动力!!!

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

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

相关文章

外汇EA如何进行历史数据回测?

很多人在下载EA后&#xff0c;直接将其投入实盘交易&#xff0c;而忽略了EA策略的优缺点以及其历史表现。尽管外汇平台提供的历史数据可能不完全准确&#xff0c;但为了确保资金安全和了解EA的真实效果&#xff0c;强烈建议在实盘交易前&#xff0c;先进行充分的历史回测。通过…

聚观早报 | 一加Ace5配置细节曝光;OpenAI重启机器人团队

聚观早报每日整理最值得关注的行业重点事件&#xff0c;帮助大家及时了解最新行业动态&#xff0c;每日读报&#xff0c;就读聚观365资讯简报。 整理丨Cutie 11月7日消息 一加Ace5配置细节曝光 OpenAI重启机器人团队 红魔10 Pro首发搭载悟空屏 华为MatePad 11.5正式发布 …

天融信运维审计系统 download 任意文件读取漏洞复现

0x01 产品描述&#xff1a; 天融信运维审计系统&#xff08;TopSAG&#xff09;是基于自主知识产权的NGTOS安全操作系统平台和多年网络安全防护经验积累研发而成&#xff0c;以4A管理理念为基础、安全代理为核心&#xff0c;提供事前预防、事中监控、事后审计的全方位运维安全解…

centos7安装java

1、首先从官网下载linux的java安装包 2、解压 tar -zxvf jdk-8u231-linux-x64.tar.gz3、修改配置文件 vim /etc/profile添加环境变量 保存后退出 4、刷新配置文件 source /etc/profile

变压吸附制氧设备的型号解析

变压吸附制氧设备(PSA制氧设备)是一种能够在常温常压条件下&#xff0c;利用PSA专用分子筛选择性吸附空气中的氮气、二氧化碳和水等杂质&#xff0c;从而取得纯度较高的氧气(一般为93%2)的设备。关于变压吸附制氧设备的型号&#xff0c;由于市场上存在众多品牌和制造商&#xf…

创新材料科技:铜冷却壁助力高炉节能降耗

高炉用铜冷却壁是高炉内部的一种构件&#xff0c;通常用于高炉的炉身部分。它的主要功能是在高炉冶炼过程中冷却炉壁&#xff0c;以防止炉壁过热。铜冷却壁通常由铜制成&#xff0c;因为铜具有良好的导热性和耐腐蚀性&#xff0c;能够有效地将热量从高炉内部传导到外部&#xf…

【数据集】【YOLO】【目标检测】电动车佩戴头盔检测数据集 5448 张,YOLO/VOC格式标注!

数据集介绍 【数据集】电动车头盔检测数据集 5448 张&#xff0c;目标检测&#xff0c;包含YOLO/VOC格式标注。数据集中包含3种分类&#xff0c;包含两轮电动车、戴头盔、不戴头盔。数据集来自国内外监控摄像头截图。检测范围电动车、摩托车、双轮非自行车。 一、数据概述 佩戴…

VBA11-row和rows的区别

一、row row返回单元格所在的行号&#xff1b; 如果是区域&#xff0c;就返回这个区域的首行的行号。 示例&#xff1a; 二、rows rows代表行的集合&#xff0c;返回range对象。 示例&#xff1a; Sub rowsTest02() 所有的行都会被选中Rows.Select第一行被选中Sheets(1).…

互联网技术人表达力提升:3个珍藏方法,快速见效!

在技术的世界中&#xff0c;逻辑是至高无上的法则&#xff1b;而在现实中&#xff0c;表达力则是成功的关键。 互联网技术人员在与他人沟通时&#xff0c;常常听到被戏称为“说人话”或“听不懂”。这种现象反映出他们在表达中使用了过多的技术术语和专业痕迹&#xff0c;而又缺…

【canal 中间件】canal 常见的启动方式

文章目录 一、安装 canal-admin1.1 拉取镜像1.2 启动 canal-admin 容器(使用脚本)1.2.1 下载脚本1.2.2 执行脚本1.2.3 初始化元数据库(可选) 1.3 启动 canal-admin 容器(直接使用 Docker 命令)1.3.1 启动容器1.3.2 查看启动日志 1.4 访问页面 二、 安装 canal-server2.1 拉取镜…

AIDOVECL数据集:包含超过15000张AI生成的车辆图像数据集,目的解决旨在解决眼水平分类和定位问题。

2024-11-01&#xff0c;由伊利诺伊大学厄巴纳-香槟分校的研究团队创建的AIDOVECL数据集&#xff0c;通过AI生成的车辆图像&#xff0c;显著减少了手动标注工作&#xff0c;为自动驾驶、城市规划和环境监测等领域提供了丰富的眼水平车辆图像资源。 数据集地址&#xff1a;AIDOV…

React 前端通过组件实现 “下载 Excel模板” 和 “上传 Excel 文件读取内容生成对象数组”

文章目录 一、Excel 模板下载01、代码示例 二、Excel 文件上传01、文件展示02、示例代码03、前端样式展示04、数据结果展示 三、完整代码 本文的业务需求是建立在批量导入数据的情况下&#xff0c;普通组件只能少量导入&#xff0c;数据较多的情况都会选择 Excel 数据导入&…

二、初识C语言(2)

1.修正 VS 下"scanf"的警告 VS-2010中调用scanf&#xff0c;会出现以下警告&#xff1a; 1>e:\c\projects\test\test\test.c(6): warning C4996: scanf: This function or variable may be unsafe. Consider using scanf_s instead. To disable deprecation, use …

使用swagger3.0踩过的坑

1.出现这个错误&#xff1a; 原因是&#xff1a; 改成&#xff1a; 就可以了 2.参数框框里面输入不了值 点击try it out &#xff0c;就可以输入了

产品的四个生命周期,产品经理需深刻理解

在产品管理的世界里&#xff0c;产品就像有生命的个体&#xff0c;经历着从诞生到消亡的过程。作为产品经理&#xff0c;深刻理解产品的四个生命周期 —— 引入期、成长期、成熟期和衰退期&#xff0c;是打造成功产品的关键。 引入期&#xff1a;破局的起点 对于 B 端产品而言&…

基于ADC12DJ5200 采样率10.4GS/s的AD子卡设计方案

FMC AD 子卡 12bit 2 通道 5.2GS/s 或单通道 10.4GS/s&#xff0c;是一款高分辨率、高采样率 ADC FMC 子板。它提 供 2 路 12 位 5.2GS/s 或 1 路 10.4GS/s 的 A/D 通 道 &#xff0c; 全功率模拟 -3dB 输入带宽可达 8GHz。本产品是基于 TI 公司ADC12DJ5200 模数转换芯片而设计…

SAP ABAP开发学习——WDA 六 控件与上下文数据编程

目录 控制器就是一个class 钩子方法&#xff08;hook method&#xff09; 组件控制器的hookmethod 普通方法的三种类型 控制器的属性 对参照使用的控制器的引用 访问数据节点 访问节点中的元素 小结1 访问单个节点的属性 取得集合中所有节点的属性 更改单个节点属性…

一文读懂| 自注意力与交叉注意力机制在计算机视觉中作用与基本原理

《博主简介》 小伙伴们好&#xff0c;我是阿旭。专注于人工智能、AIGC、python、计算机视觉相关分享研究。 &#x1f44d;感谢小伙伴们点赞、关注&#xff01; 《------往期经典推荐------》 一、AI应用软件开发实战专栏【链接】 项目名称项目名称1.【人脸识别与管理系统开发…

手动切换python版本

本地有多个python版本&#xff0c;在没有安装anaconda工具&#xff0c;需要手动切换环境需要的操作。 目录 1、建立目录 建立pip的本地目录&#xff0c;如下图&#xff1a; 2、打开系统环境变量&#xff0c;增加变量 打开系统环境变量&#xff0c;我这里用的是“编辑帐户的…

在 ASP.NET Core 6.0 中使用 Swagger/OpenAPI 丰富 Web API 文档

示例代码&#xff1a;https://download.csdn.net/download/hefeng_aspnet/89961435 介绍 在选择或尝试与 API 集成之前&#xff0c;大多数开发人员都会查看其 API 文档。保持 API 文档更新以反映软件更改是一项挑战&#xff0c;需要时间和精力。对于 Web API&#xff0c;我们…