LeetCode10 Indexed tree
Binary Indexed Tree(Fenwick tree):
是一个查询和修改复杂度都为log(n)的数据结构。主要用于查询任意两位之间的所有元素之和,但是每次只能修改一个元素的值;经过简单修改可以在log(n)的复杂度下进行范围修改,但是这时只能查询其中一个元素的值(如果加入多个辅助数组则可以实现区间修改与区间查询)
原理:
树状数组是不需要建树的,通过lowbit来建立一个sum数组(此处为c数组)来维护原来的数组
Lowbit讲解:
c[i]=sum(a[j]) i - lowbit(i) + 1 <= j <= i;
这里的 lowbit(i) 表示将i转换成二进制后的最右边的1到最后所形成的十进制的数。
例如 lowbit(6)=lowbit(110)2=(10)2=2
所以 c[6]=a[5]+a[6];
lowbit(4)=lowbit(100)2=(100)2=4
c[4]=a[1]+a[2]+a[3]+a[4]
lowbit[5]=lowbit(101) 2 =(1) 2=1;
c[5]=a[5]
Lowbit公式:
- lowbit(i)=i&(-i);
公式原理:
上面这个公式是非常重要的,就是通过求出一个数的 Lowbit 将这些数据建立成一个树的,父子节点和线段树关系类似,都是通过某种固定的方式建立起来的。而 lowbit 的原理就是利用了计算机里面的反码和补码(这世界本来就是二进制的!)
我们都知道在计算机中数使用二进制存储的,int 是 4 字节,例如我们把5换成二进制。 5=00000000 00000000 00000000 00000101 这同时也是5的原码。 原码:一个正数,按照值大小转换成的二进制数;一个负数按照绝对值大小转换成的二进制数,然后最高位补1,称为原码。
那么-5的原码就是 -5=10000000 00000000 00000000 00000101 ,其中,最高位的1是符号位。 在计算机中储存一个数用的是补码的形式,要了解补码需要先知道什么是反码。 反码:正数的反码与原码相同,负数的反码为对该数的原码除符号位外各位取反 -5的反码就是: 11111111 11111111 11111111 11111010
再说补码:正数的补码与原码相同,负数的补码是这个数的反码+1 -5:11111111 11111111 11111111 11111010+1= 11111111 11111111 11111111 11111011
那么我们利用这个公式 x&(-x) 的意义:
6&(-6):
6: 00000000 00000000 00000000 00000110
-6: 11111111 11111111 11111111 11111010
Ans: 00000000 00000000 00000000 00000010
所以说 lowbit(6) 的结果很明显就是2
节点i的父亲节点为i+lowbit(i) 若需改变a[i],则c[i]、c[i+lowbit(i)]、 c[i+lowbit(i)+lowbit(i+lowbit(i)]……一直加到上限,就是需要改变的c数组中的元素。
若需查询s[i],则 c[i] 、 c[i-lowbit(i)] 、c[i-lowbit(i)-lowbit(i-lowbit(i))] ……就是需要累加的c数组中的元素。 这样我们就让复杂度优化到了 O(logn)
public void change(int index, int val){
while (index <= maxValue){
sum[index] += val;
index += index & (- index);
}
}
public int sum(int index){
int sum = 0;
while( index >= 0){
sum += sum[index];
index -= index & (-index);
}
}
树状数组原理图:

herf: http://xorex.top/2017/05/20/二叉索引树-树状数组-——讲解/
2D Binary Indexed Tree (Fenwick Tree)
Algorithm:
We consider the below example. Suppose we have to find the sum of all numbers inside the highlighted area-
We assume the origin of the matrix at the bottom – O.Then a 2D BIT exploits the fact that-
Sum under the marked area = Sum(OB) - Sum(OD) - Sum(OA) + Sum(OC)


In our program, we use the getSum(x, y) function which finds the sum of the matrix from (0, 0) to (x, y).
Hence the below formula :Sum under the marked area = Sum(OB) - Sum(OD) - Sum(OA) + Sum(OC)
The above formula gets reduced to,
Query(x1,y1,x2,y2) = getSum(x2, y2) - getSum(x2, y1-1) - getSum(x1-1, y2) + getSum(x1-1, y1-1) ;
308. Range Sum Query 2D - Mutable
class NumMatrix {
int [][] tree;
int [][] matrix;
int m;
int n;
public NumMatrix(int[][] matrix) {
if(matrix.length == 0 || matrix[0].length == 0) return;// 先判断,再赋值。因为有可能,matrix.length = 0, 那么matrix[0]就会out index boundary。所以上述顺序也不能改变。
m = matrix.length;
n = matrix[0].length;
tree = new int[m + 1][n + 1];//对应的[m][n]的信息其实是存在[m+1][n+1]中
this.matrix = new int[m][n];
for(int i = 0; i < m; ++i){
for(int j = 0; j < n; ++j){
update(i, j, matrix[i][j]);
}
}
}
public void update(int row, int col, int val) {
if(m == 0 || n == 0) return;
int update = val - matrix[row][col];
matrix[row][col] = val;//必须要新立一个matrix,因为input只是一个variable,需要一个成员变量来保存
for(int i = row + 1; i <= m; i += i & (-i)){
for(int j = col + 1; j <= n; j += j & (-j)){
tree[i][j] += update;
}
}
}
public int sumRegion(int row1, int col1, int row2, int col2) {
if(m == 0 || n == 0) return 0;
return sum(row2 + 1, col2 + 1) + sum(row1, col1) - sum(row1, col2 + 1) - sum(row2 + 1, col1);
}
public int sum(int row, int col){
int sum = 0;
for(int i = row; i > 0; i -= i & (-i)){
for(int j = col; j > 0; j -= j & (-j)){
sum += tree[i][j];
}
}
return sum;
}
}
- Time Complexity :
- Both update and sumRegion function takes O(log(MN)) time.
- Building the 2D tree takes O(NM log(NM))
- Answering Q queries takes O(Qlog(NM))
- M = matrix.length N = matrix[0].length
LeetCode10 Indexed tree的更多相关文章
- Leetcode: Range Sum Query 2D - Mutable && Summary: Binary Indexed Tree
Given a 2D matrix matrix, find the sum of the elements inside the rectangle defined by its upper lef ...
- SRM 627 D1L2GraphInversionsDFS查找指定长度的所有路径 Binary indexed tree (BIT)
题目:http://community.topcoder.com/stat?c=problem_statement&pm=13275&rd=16008 由于图中边数不多,选择DFS遍历 ...
- 树状数组(Binary Indexed Tree,BIT)
树状数组(Binary Indexed Tree) 前面几篇文章我们分享的都是关于区间求和问题的几种解决方案,同时也介绍了线段树这样的数据结构,我们从中可以体会到合理解决方案带来的便利,对于大部分区间 ...
- Binary Indexed Tree (Fenwick Tree)
Binary Indexed Tree 主要是为了存储数组前缀或或后缀和,以便计算任意一段的和.其优势在于可以常数时间处理更新(如果不需要更新直接用一个数组存储所有前缀/后缀和即可).空间复杂度O(n ...
- 【计数】hdu5921Binary Indexed Tree
二进制拆位计算贡献 题目描述 树状数组是一种常用的数据结构,下面是树状数组用于给区间 [1,x] 内的数加 t 的代码: void add(int x,int t){ for (int i=x;i;i ...
- Hdu5921 Binary Indexed Tree
Hdu5921 Binary Indexed Tree 思路 计数问题,题目重点在于二进制下1的次数的统计,很多题解用了数位DP来辅助计算,定义g(i)表示i的二进制中1的个数, $ans = \su ...
- Binary Indexed Tree 总结
特点 1. 针对 数组连续子序列累加和 问题(需要进行频繁的 update.sum 操作): 2. 并非是树型结构,只是逻辑上层次分明: 3. 可以通过 填坑法 来理解: 4. 中心思想:每一个整数都 ...
- Binary Indexed Tree
我借鉴了这个视频中的讲解的填坑法,我认为非常易于理解.有FQ能力和基本英语听力能力请直接去看视频,并不需要继续阅读. naive 算法 考虑一个这样的场景: 给定一个int数组, 我们想知道它的连续子 ...
- 树状数组(Binary Indexed Tree)
树状数组(Binary Indexed Tree,BIT) 是能够完成下述操作的数据结构. 给一个初始值全为 0 的数列 a1, a2, ..., an (1)给定 i,计算 a1+a2+...+ai ...
随机推荐
- Ext.js性能优化漫谈
Ext.js是一个用于建立企业级应用的纯JS框架.毫无疑问,它为我们提供了大量的组件,比如container,panel,field,grid,这些组件使用起来很方便,不需要去写js和html,但是e ...
- eclipse hibernate配置文件(*.hbm.xml)加上自动提示功能
转自:https://blog.csdn.net/u012217085/article/details/17397843?utm_source=blogkpcl3 1. 标签:hibernate 在编 ...
- dotnet ef执行报错, VS 2019发布时配置项中的Entity Framework迁移项显示不出来
VS 2019发布时配置项中的Entity Framework迁移项显示不出来 dotnet ef dbcontext list --json “无法执行,因为找不到指定的命令或文件.可能的原因包括: ...
- CSS3 flexbox弹性布局实例
常用例子 1.居中对齐 <!DOCTYPE html> <head> <meta charset="utf-8"> <style type ...
- Tenka1 Programmer Contest D - Crossing
链接 Tenka1 Programmer Contest D - Crossing 给定\(n\),要求构造\(k\)个集合\({S_k}\),使得\(1\)到\(n\)中每个元素均在集合中出现两次, ...
- BZOJ 5046 分糖果游戏
网页崩溃了 心态也崩溃了 MD劳资写了那么多 题意: 有a,b两个人分糖,每个人都有一个能量值.每个人每一轮可以选择进行两种操作: 1.取走最左边的糖果,补充相应的能量值并获取相应的美味度. 2.跳过 ...
- (arm板子tensorflow安装)armv7板子pip安装的wheel
树莓派之类的armv7板子在,安装 numpy,scipy时经常失败,因为安装过程是下载源码包到本地编译,然后再安装的,编译过程中往往就会失败. https://www.piwheels.org/si ...
- simulate 中的一些操作
1. neutralize: position based 的alpha int neutralize(int di, int ti) { ; ; ; ; ii < nsyms; ++ii) { ...
- PHP实现跨服务器session共享的方法教程
今天带来PHP实现跨服务器session共享的方法教程. 本文实例讲述了PHP实现cookie跨域session共享的方法.分享给大家供大家参考,具体如下: 做过web开发的小伙伴们都了解cookie ...
- ubuntu 18.04设置系统自带系统截图快捷键
0.前言 ubuntu 18.04自带一个截图工具gnome-screenshot,有三种模式,全屏截图.当前活动窗口截图.选取活动区域截图 1.设置快捷键 Setting->Devices-& ...