IndexTree

简介: IndexTree

IndexTree解决的问题

在这里插入图片描述

线段树支持区间更新,但是IndexTree只支持单点更新。

假设给定一个数组,如果频繁的要求某个范围的累加和,在原数组不变的情况下,可以申请一个辅助数组做前缀和(help),然后只需要在辅助数组查询两次就可以得到某个范围上的累加和了!

但是,如果原数组某个变动了的话,前缀和就无法实现了

所以要用到IndexTree,下图表示help数组每个位置记录原数组哪些范围,比如:1位置记录的是原数组1到1位置上的累加和、2位置记录的是原数组1到2位置上的累加和...

help数组不是上面提到的前缀和数组!!!

在这里插入图片描述

两个规律

第一个:假设某一个index的二进制表示形式如下,index为help数组中的下标i,那么index位置的值表示记录原数组哪些范围的值呢?010110001 ~ 010111000
在这里插入图片描述
举例
在这里插入图片描述
在这里插入图片描述
第二个:如果想求原数组中从 1 ~ i 位置的前缀和,假设 i 为33,如何利用help数组求?
在这里插入图片描述
i 转换为二进制形式,33位置上只管自己,但是32位置上管的是从1到32位置上的所有,所以它两一累加就实现了1到33的累加
在这里插入图片描述
假设要求原数组中从1到index位置的累加和(index等于52,index的二进制是 0110100),如何利用help数组求?

help[0110100] + help[0110000] + help[0100000]

那么help数组中index位置上管的是原数组中哪些范围的值呢?

help[0110100] = help[0110001] ~ help[0110100]
help[0110000] = help[0100001] ~ help[0110000]
help[0100000] = help[0000001] ~ help[0100000]

仔细看上面红色加粗字体(从下往上看),是不是就是连起来了呢,所以原数组中从1到index位置的累加和就这样利用help数组求出来了

在这里插入图片描述

add方法

假设原数组中3位置的值发生了变化,那么如何知道help数组中哪些位置的值也发生了变化呢?
在这里插入图片描述
将3化为二进制形式后,提取出最右侧的1再加上自己,

011 -> 100 -> 1000 -> 10000...,那么在help数组中,这些位置的数都随之发生改动。
在这里插入图片描述

时间复杂度

O(logN),因为是在位信息上操作,有几个位信息就做几次操作,位数就是logN次

总结

一维IndexTree很容易的实现了单点更新和 1 ~ index位置上的前缀和,

如何实现任意一个范围 L到R的前缀和呢?

稍微一加工就可以了:1到R 减去 1到L-1 就实现了

问题是这些功能线段树也可以实现,并且时间复杂度都一样,那么IndexTree存在的意义是什么呢?

线段树是一维的,推成二维很麻烦,而IndexTree推成二维很容易!!!

代码实现

package com.harrison.class22;

/**
 * @author Harrison
 * @create 2022-04-02-9:39
 * @motto 众里寻他千百度,蓦然回首,那人却在灯火阑珊处。
 */
public class Code01_IndexTree {
    // 下标从1开始
    public static class IndexTree{
        private int[] tree;
        private int N;

        // 0位置弃而不用
        public IndexTree(int size){
            N=size;
            tree=new int[N+1];
        }

        // 1~index累加和是多少
        /*
        补充一个小知识:负数的二进制用其正数的补码形式表示
        补码:反码+1
         */
        public int sum(int index){
            int ret=0;
            while(index>0){
                ret+=tree[index];
                index-=index&(-index);// index-=(index & (~index+1))
            }
            return ret;
        }

        // index & -index : 提取出index最右侧的1出来
        // index :           0011001000
        // index & -index :  0000001000
        public void add(int index,int d){
            while(index<=N){
                tree[index]+=d;
                index+=index&(-index);
            }
        }
    }

    public static class Right{
        private int[] nums;
        private int N;

        public Right(int size){
            N=size+1;
            nums=new int[N+1];
        }

        public int sum(int index){
            int ret=0;
            for(int i=1; i<=index; i++){
                ret+=nums[i];
            }
            return ret;
        }

        public void add(int index,int d){
            nums[index]+=d;
        }
    }

    public static void main(String[] args) {
        int N = 100;
        int V = 100;
        int testTime = 2000000;
        IndexTree tree = new IndexTree(N);
        Right test = new Right(N);
        System.out.println("test begin");
        for (int i = 0; i < testTime; i++) {
            int index = (int) (Math.random() * N) + 1;
            if (Math.random() <= 0.5) {
                int add = (int) (Math.random() * V);
                tree.add(index, add);
                test.add(index, add);
            } else {
                if (tree.sum(index) != test.sum(index)) {
                    System.out.println("Oops!");
                }
            }
        }
        System.out.println("test finish");
    }
}
相关文章
|
Linux
Xshell 登录 AWS CentOS 出现“所选择的用户秘钥未在远程主机上注册“,最终解决办法!
其实就是 登录用户名错了,是 root,不是centos 也不是 ec2-user !  Xshell 连接配置界面如下   最重要是 登录授权配置  最后,登录成功! 就这么简单
2838 0
|
5月前
|
算法 测试技术 C#
【模拟】【C++算法】2826. 将三个组排序
【模拟】【C++算法】2826. 将三个组排序
|
网络安全 数据安全/隐私保护
阿里云Permission denied (publickey,gssapi-keyex,gssapi-with-mic)
阿里云Permission denied (publickey,gssapi-keyex,gssapi-with-mic)
371 0
|
3天前
|
SQL 人工智能 安全
【灵码助力安全1】——利用通义灵码辅助快速代码审计的最佳实践
本文介绍了作者在数据安全比赛中遇到的一个开源框架的代码审计过程。作者使用了多种工具,特别是“通义灵码”,帮助发现了多个高危漏洞,包括路径遍历、文件上传、目录删除、SQL注入和XSS漏洞。文章详细描述了如何利用这些工具进行漏洞定位和验证,并分享了使用“通义灵码”的心得和体验。最后,作者总结了AI在代码审计中的优势和不足,并展望了未来的发展方向。
|
11天前
|
编解码 Java 程序员
写代码还有专业的编程显示器?
写代码已经十个年头了, 一直都是习惯直接用一台Mac电脑写代码 偶尔接一个显示器, 但是可能因为公司配的显示器不怎么样, 还要接转接头 搞得桌面杂乱无章,分辨率也低,感觉屏幕还是Mac自带的看着舒服
|
18天前
|
存储 人工智能 缓存
AI助理直击要害,从繁复中提炼精华——使用CDN加速访问OSS存储的图片
本案例介绍如何利用AI助理快速实现OSS存储的图片接入CDN,以加速图片访问。通过AI助理提炼关键操作步骤,避免在复杂文档中寻找解决方案。主要步骤包括开通CDN、添加加速域名、配置CNAME等。实测显示,接入CDN后图片加载时间显著缩短,验证了加速效果。此方法大幅提高了操作效率,降低了学习成本。
2784 8
|
13天前
|
存储 缓存 关系型数据库
MySQL事务日志-Redo Log工作原理分析
事务的隔离性和原子性分别通过锁和事务日志实现,而持久性则依赖于事务日志中的`Redo Log`。在MySQL中,`Redo Log`确保已提交事务的数据能持久保存,即使系统崩溃也能通过重做日志恢复数据。其工作原理是记录数据在内存中的更改,待事务提交时写入磁盘。此外,`Redo Log`采用简单的物理日志格式和高效的顺序IO,确保快速提交。通过不同的落盘策略,可在性能和安全性之间做出权衡。
1576 12
|
5天前
|
人工智能 关系型数据库 Serverless
1024,致开发者们——希望和你一起用技术人独有的方式,庆祝你的主场
阿里云开发者社区推出“1024·云上见”程序员节专题活动,包括云上实操、开发者测评和征文三个分会场,提供14个实操活动、3个解决方案、3 个产品方案的测评及征文比赛,旨在帮助开发者提升技能、分享经验,共筑技术梦想。
715 95
|
1月前
|
弹性计算 人工智能 架构师
阿里云携手Altair共拓云上工业仿真新机遇
2024年9月12日,「2024 Altair 技术大会杭州站」成功召开,阿里云弹性计算产品运营与生态负责人何川,与Altair中国技术总监赵阳在会上联合发布了最新的“云上CAE一体机”。
阿里云携手Altair共拓云上工业仿真新机遇
|
18天前
|
人工智能 Serverless API
AI助理精准匹配,为您推荐方案——如何快速在网站上增加一个AI助手
通过向AI助理提问的方式,生成一个技术方案:在网站上增加一个AI助手,提供7*24的全天候服务,即时回答用户的问题和解决他们可能遇到的问题,无需等待人工客服上班,显著提升用户体验。
1468 9