307. 区域和检索 - 数组可修改
给你一个数组 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]
)
https://leetcode.cn/problems/range-sum-query-mutable/solutions/632515/guan-yu-ge-lei-qu-jian-he-wen-ti-ru-he-x-41hv/?envType=daily-question&envId=2023-11-13
参考题解:宫水三叶
各类区间和问题:
情况一:数组不变,求区间和
「前缀和」、「树状数组」、「线段树」
情况二:多次修改某个数(单点),求区间和
「树状数组」、「线段树」
情况三:多次修改某个区间,输出最终结果
「差分」
情况四:多次修改某个区间,求区间和
「线段树」、「树状数组」(看修改区间范围大小)
情况五:多次将某个区间变成同一个数,求区间和
「线段树」、「树状数组」(看修改区间范围大小)
线段树代码长而且性能不稳定,所以只有迫不得已的时候才会使用线段树。所以遇到情况四的时候才使用线段树。
本题属于情况二,使用树状数组解决,当做模板直接背过
【树状树组】树状树组模板_暮色_年华的博客-CSDN博客
class NumArray {
public:vector<int>tree;int lowbit(int x){return x&-x;}int query(int x){int ans = 0;for(int i = x;i > 0;i-=lowbit(i))ans += tree[i];return ans;}void add(int x,int u){for(int i = x;i<=n;i+=lowbit(i))tree[i]+=u;}vector<int>nums;int n;NumArray(vector<int>& nums) {this->nums = nums;n = nums.size();tree.resize(n+1,0);for(int i = 0;i < n;i++)add(i+1, nums[i]);}void update(int index, int val) {add(index+1, val - nums[index]);nums[index] = val;}int sumRange(int left, int right) {return query(right+1)-query(left);}
};/*** Your NumArray object will be instantiated and called as such:* NumArray* obj = new NumArray(nums);* obj->update(index,val);* int param_2 = obj->sumRange(left,right);*/