• 博客园logo
  • 会员
  • 众包
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • HarmonyOS
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录
Niro Einteson
文可提笔安天下 武可上马定乾坤
博客园    首页    新随笔    联系   管理    订阅  订阅

307. 区域和检索 - 数组可修改

307. 区域和检索 - 数组可修改

 

给定一个整数数组  nums,求出数组从索引 i 到 j  (i ≤ j) 范围内元素的总和,包含 i,  j 两点。

update(i, val) 函数可以通过将下标为 i 的数值更新为 val,从而对数列进行修改。

示例:

Given nums = [1, 3, 5]

sumRange(0, 2) -> 9
update(1, 2)
sumRange(0, 2) -> 8

说明:

  1. 数组仅可以在 update 函数下进行修改。
  2. 你可以假设 update 函数与 sumRange 函数的调用次数是均匀分布的。

常规想法-代码

 

 1 class NumArray {
 2 public:
 3     vector<int> number;
 4     vector<int> sum;
 5     NumArray(vector<int>& nums) {
 6         if(nums.empty()) return ;
 7         sum.push_back(nums[0]);
 8         number.push_back(nums[0]);// number=nums;直接赋值
 9         for(int i=1;i<nums.size();i++){
10             sum.push_back(sum[i-1]+nums[i]);
11             number.push_back(nums[i]);
12         }
13     }
14     
15     void update(int i, int val) {
16         
17         int tmp=number[i];
18         number[i]=val;
19         for(int j=i;j<number.size();j++){
20             sum[j]+=val-tmp;
21         }
22     }
23     
24     int sumRange(int i, int j) {
25         if(i==0) return sum[j];
26         return sum[j]-sum[i-1];
27 
28     }
29 };

 

 

 

树状数组-代码

 

 1 class BitTree{//这里面 不需要加public
 2 public:
 3     vector<int> arr;
 4     BitTree(){}
 5     BitTree(vector<int>& nums){
 6         arr.push_back(0);//从1  到 n 存储赋值,下标0 不用 大小n+1个;
 7         for(int i=0;i<nums.size();i++){
 8             arr.push_back(nums[i]);
 9         }
10         for(int i=1;i<arr.size();i++){
11             int j=i+(i&-i);
12             if(j<arr.size()){//最后一个的下标 位 arr.size()-1
13                 arr[j]+=arr[i];//arr[j]=arr[j]+arr[i];
14             }
15         }
16     }
17     void update(int index,int val){//代表 在 index位置上 加上val,之后更新相应位置
18         index+=1;//下标往后移动1位,因为 数据在 1 到n
19         while(index<arr.size()){
20             arr[index]+=val;
21             index=index+(index&-index);
22         }
23     }
24     int prefixSum(int index){//前缀和
25         index+=1;
26         int sum=0;
27         while(index>0){
28             sum+=arr[index];
29             index=index-(index&-index);
30         }
31         return sum;
32     }
33 };
34 
35 class NumArray {
36 public:
37     vector<int> number;//存储原来的值
38     BitTree btree;//树状数组
39     NumArray(vector<int>& nums) {
40         if(nums.empty()) return ;
41         number=nums;
42         btree=BitTree(nums);
43     }
44     
45     void update(int i, int val) {
46         btree.update(i,val-number[i]);//增加的值 是 val-nums[i]
47         number[i]=val;//更新这个位置的值
48     }
49     
50     int sumRange(int i, int j) {
51         //if(i==0) return btree.prefixSum(j);
52         return btree.prefixSum(j)-btree.prefixSum(i-1);
53     }
54 };

 

 

 

线段树-代码

 

 1 class NumArray {
 2 public:
 3     struct tree{
 4         int left,right;
 5         int data;
 6     };
 7     vector<tree> dt;
 8     vector<int> number;
 9     void build_tree(int pos,int start,int end){
10         dt[pos].left=start,dt[pos].right=end;//保存节点的区间
11         if(start==end){//叶子
12             dt[pos].data=number[start-1];//存值, start是 索引多加了1,所以 取数据的时候减去
13             return ;
14         }
15         int mid=(start+end)/2;
16         build_tree(pos<<1,start,mid);//创建左子树
17         build_tree(pos<<1|1,mid+1,end);//右子树
18         dt[pos].data=dt[pos<<1].data+dt[pos<<1|1].data;//节点和 更新
19         //pos=1  开始 , 左孩子 2*pos,右孩子 2*pos+1;  2*pos=pos<<1;2*pos+1=pos<<1|1;
20         //pos=0 开始,左孩子 2*pos+1,右孩子2*pos+2;
21     }
22     void Update_val(int pos,int index,int val){
23         if(dt[pos].left==dt[pos].right){
24             dt[pos].data=val;//叶子节点
25             return ;
26         }
27         int mid=(dt[pos].left+dt[pos].right)/2;
28         if(index<=mid){//在左子树上
29             Update_val(pos<<1,index,val);
30         }else{//在右子树上
31             Update_val(pos<<1|1,index,val);
32         }//更新节点和
33         dt[pos].data=dt[pos<<1].data+dt[pos<<1|1].data;
34     }
35     int query(int pos,int start,int end){
36         //if(dt[pos].left>end||dt[pos].right<start) return 0;
37         if(dt[pos].left>=start&&dt[pos].right<=end){
38             return dt[pos].data;
39         }
40         int mid=(dt[pos].left+dt[pos].right)/2;
41         if(start>mid) return query(pos<<1|1,start,end);//在右边 ,是右孩子
42         if(end<=mid) return query(pos<<1,start,end);//在左边是 左孩子
43         return query(pos<<1,start,end)+query(pos<<1|1,start,end);//两边都有
44     }
45     NumArray(vector<int>& nums) {
46         if(nums.size()==0) return ;
47         int len=nums.size();//获取数组的长度
48         number=nums;       
49         dt=vector<tree>(4*len);//开四倍空间 // vector<tree> tmp(4*len); dt=tmp;
50         build_tree(1,1,len);//下标为 len
51     }    
52     void update(int i, int val) {
53         Update_val(1,i+1,val);//更新,从 1 根节点,更新 索引i 实际,下标要+1;
54     }    
55     int sumRange(int i, int j) {
56         return query(1,i+1,j+1);//查询区间的下标要加1
57     }
58 };

 

 

线段树-代码

 1 class NumArray {
 2 public:
 3     struct tree{
 4         int left,right;
 5         int data;
 6     };
 7     vector<tree> dat;
 8    // vector<int> number;
 9     void build_tree(vector<tree>& dt,vector<int>& number,int pos,int start,int end){
10         dt[pos].left=start,dt[pos].right=end;//保存节点的区间
11         if(start==end){//叶子
12             dt[pos].data=number[start-1];//存值, start是 索引多加了1,所以 取数据的时候减去
13             return ;
14         }
15         int mid=(start+end)/2;
16         build_tree(dt,number,pos<<1,start,mid);//创建左子树
17         build_tree(dt,number,pos<<1|1,mid+1,end);//右子树
18         dt[pos].data=dt[pos<<1].data+dt[pos<<1|1].data;//节点和 更新
19 
20     }
21     void Update_val(vector<tree>& dt,int pos,int index,int val){
22         if(dt[pos].left==dt[pos].right){
23             dt[pos].data=val;//叶子节点
24             return ;
25         }
26         int mid=(dt[pos].left+dt[pos].right)/2;
27         if(index<=mid){//在左子树上
28             Update_val(dt,pos<<1,index,val);
29         }else{//在右子树上
30             Update_val(dt,pos<<1|1,index,val);
31         }//更新节点和
32         dt[pos].data=dt[pos<<1].data+dt[pos<<1|1].data;
33     }
34     int query(vector<tree>& dt,int pos,int start,int end){
35         //if(dt[pos].left>end||dt[pos].right<start) return 0;
36         if(dt[pos].left>=start&&dt[pos].right<=end){
37             return dt[pos].data;
38         }
39         int mid=(dt[pos].left+dt[pos].right)/2;
40         if(start>mid) return query(dt,pos<<1|1,start,end);//在右边 ,是右孩子
41         if(end<=mid) return query(dt,pos<<1,start,end);//在左边是 左孩子
42         return query(dt,pos<<1,start,end)+query(dt,pos<<1|1,start,end);//两边都有
43     }
44     NumArray(vector<int>& nums) {
45         if(nums.size()==0) return ;
46         int len=nums.size();//获取数组的长度
47         vector<tree> tmp(4*len);//开四倍空间
48         dat=tmp;
49         build_tree(dat,nums,1,1,len);
50         //pos=1  开始 , 左孩子 2*pos,右孩子 2*pos+1;
51         //pos=0 开始,左孩子 2*pos+1,右孩子2*pos+2;
52     }
53     
54     void update(int i, int val) {
55         Update_val(dat,1,i+1,val);//更新,从 1 根节点,更新 索引i 实际,下标要+1;
56     }
57     
58     int sumRange(int i, int j) {
59         return query(dat,1,i+1,j+1);//查询区间的下标要加1
60     }
61 };

 

秀

 1 class NumArray {
 2 public:
 3     vector<int> t;
 4     int n;  // array size
 5     void build() {  // build the tree
 6          for (int i = n - 1; i > 0; --i) t[i] = t[i<<1] + t[i<<1|1];
 7     }
 8     void modify(int p, int value) {  // set value at position p
 9         for (t[p += n] = value; p > 1; p >>= 1) t[p>>1] = t[p] + t[p^1];
10     }
11     int query(int l, int r) {  // sum on interval [l, r)
12         int res = 0;
13         for (l += n, r += n; l <r; l >>= 1, r >>= 1) {
14             if (l&1) res += t[l++];
15             if (r&1) res += t[--r];
16         }
17         return res;
18     }
19     NumArray(vector<int>& nums) {
20         if(nums.size()==0) return ;
21         n=nums.size();//获取数组的长度
22         t=vector<int>(3*n);
23         for(int i=0;i<n;i++){
24             t[i+n]=nums[i];
25         }
26         build();
27     }    
28     void update(int i, int val) {
29         modify(i,val);//从0开始的
30     }    
31     int sumRange(int i, int j) {
32         return query(i,j+1);
33     }
34 };

 

posted @ 2020-03-23 12:16  Nirogo  阅读(290)  评论(0)    收藏  举报
刷新页面返回顶部
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3