给你一个数组 nums ,请你完成两类查询。
其中一类查询要求 更新 数组 nums 下标对应的值
另一类查询要求返回数组 nums 中索引 left 和索引 right 之间( 包含 )的nums元素的 和 ,其中 left <= right
实现 NumArray 类:
- NumArray(int[] nums) 用整数数组 nums 初始化对象
- void update(int index, int val) 将 nums[index] 的值 更新 为 val
- int sumRange(int left, int right) 返回数组 nums 中索引 left 和索引 right 之间( 包含 )的nums元素的 和 (即,nums[left] + nums[left + 1], ..., nums[right])
最开始看题使用的暴力法,在 *** 作次数和调用查询 *** 作同阶市,时间复杂度
O
(
n
2
)
O(n^2)
O(n2),因此会超出时间限制,在看题解后知道了树状数组。
思路如下:
将C[]数组的结点序号转化为二进制
1=(001) C[1]=A[1];
2=(010) C[2]=A[1]+A[2];
3=(011) C[3]=A[3];
4=(100) C[4]=A[1]+A[2]+A[3]+A[4];
5=(101) C[5]=A[5];
6=(110) C[6]=A[5]+A[6];
7=(111) C[7]=A[7];
8=(1000) C[8]=A[1]+A[2]+A[3]+A[4]+A[5]+A[6]+A[7]+A[8];
第i个位置上的值为叶节点的和,这个和是通过二进制最后的0的个数所确定,一共需要2^k,k为0的个数,比如C[4] = A[0] + A[1] + A[2] + A[3],这是因为4的二进制数为:100,末尾一共有两个0,因此一共由前面4个数确定。
下面利用C数组计算子缀和,当计算前i个子缀和时,假设i=7
sum[7] = A[1]+A[2]+A[3]+A[4]+A[5]+A[6]+A[7]
前i项和 :sum[7] = C[4] + C[6] + C[7]
利用C数组是怎么算的呢?先看代码
int getsum(int x){
int ans=0;
for(int i=x;i>0;i-=lowbit(i))
ans+=C[i];
return ans;
}
这里先引进 l o w b i t lowbit lowbit函数: l o w b i t = x & ( − x ) lowbit = x \& (-x) lowbit=x&(−x)
int lowbit(int x){
return x & (-x);
}
通过lowbit *** 作不断将目标点的最后一个1反转成0,达到前缀求和 *** 作。
比如
x
=
7
=
111
x = 7 = 111
x=7=111
ans += C[7]
-x = 001
x & -x = 001
x - lowbit(x) = 110 = 6
ans += C[6]
-x = 010 = 2
x & -x = 010 = 2
x - lowbit(x) = 100 = 4
ans += C[4]
-x = 001
x & (-x) = 000 = 0
结束
可以看见C[7]通过3个值来计算出结果。
上面说的“不断将目标点的最后一个1反转成0” *** 作,从计算过程中可以看出 111 --> 110 --> 100 --> 000
单点更新当我们修改A[]数组中的某一个值时 应当如何更新C[]数组呢?
回想一下 区间查询的过程,再看一下上文中列出的图
void add(int x,int y)
{
for(int i=x;i<=n;i+=lowbit(i))
tree[i]+=y;
}
可以发现 更新过程是查询过程的逆过程。
由叶子结点向上更新C[]数组,也就是不断把1反转成0的过程。
当更新A[1]时 需要向上更新C[1] ,C[2],C[4],C[8]
C[1], C[2], C[4], C[8]
写为二进制 C[(001)],C[(010)],C[(100)],C[(1000)]
1(001) C[1]+=A[1]
lowbit(1)=001 1+lowbit(1)=2(010) C[2]+=A[1]
lowbit(2)=010 2+lowbit(2)=4(100) C[4]+=A[1]
lowbit(4)=100 4+lowbit(4)=8(1000) C[8]+=A[1]
那么初始化C数组就是不断读取A中的初始值,然后循环add函数
add(i+1, A[i]);
Reference
https://leetcode-cn.com/circle/article/F8YCEM/
https://www.cnblogs.com/hsd-/p/6139376.html
https://flushhip.blog.csdn.net/article/details/79165701?spm=1001.2101.3001.6650.1&utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7ERate-1.pc_relevant_aa&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7ERate-1.pc_relevant_aa&utm_relevant_index=2
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)