zoukankan      html  css  js  c++  java
  • 307. 区域和检索

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

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

    update(i, val) 函数可以通过将下标为 的数值更新为 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 };
  • 相关阅读:
    潭州课堂25班:Ph201805201 第十二课 new方法,定制属性访问,描述符与装饰器 (课堂笔记)
    潭州课堂25班:Ph201805201 第十一课 继承,多继承和魔术方法,属性和方法 (课堂笔记)
    Storm笔记
    java代码。继承。。。很戳我的心啊。。不太懂。super的真正用法
    java代码。从来没想过java里的继承是多么的难懂。如哲学
    java代码继承疑惑,请有心人解答
    java冒泡排序
    java数组复制
    java继承。顾不了
    java继承初级
  • 原文地址:https://www.cnblogs.com/NirobertEinteson/p/12551391.html
Copyright © 2011-2022 走看看