リージョンと検索-配列は変更可能

1.エリアと検索-配列は変更可能

1.1、タイトル要件

配列番号を指定して、2種類のクエリを実行してください。

  1. クエリの1つのタイプでは、配列numsの添え字に対応する値を更新する必要があります。
  2. 別のタイプのクエリは、配列nums内の(包括的)インデックスleftとインデックスrightの間のnumsの要素の合計を返すように要求します。ここでleft <= right

NumArrayクラスを実装します。

  1. NumArray(int [] nums)は、整数配列numsでオブジェクトを初期化します。
  2. void update(int index、int val)nums[index]の値をvalに更新します。
  3. int sumRange(int left、int right)配列nums内の(両端を含む)indexleftとindexrightの間のnumsの要素の合計を返します(つまり、nums [left] + nums [left + 1]、…、nums [right ])。
示例 1
输入:
["NumArray", "sumRange", "update", "sumRange"]
[[[1, 3, 5]], [0, 2], [1, 2], [0, 2]]
输出:
[null, 9, null, 8]

解释:
NumArray numArray = new NumArray([1, 3, 5]);
numArray.sumRange(0, 2); // 返回 1 + 3 + 5 = 9
numArray.update(1, 2);   // nums = [1,2,5]
numArray.sumRange(0, 2); // 返回 1 + 2 + 5 = 8

提示:
1 <= nums.length <= 3 * 104
-100 <= nums[i] <= 100
0 <= index < nums.length
-100 <= val <= 100
0 <= left <= right < nums.length
调用 pdate 和 sumRange 方法次数不大于 3 * 104 

ソース:LeetCode
リンク:https ://leetcode-cn.com/problems/range-sum-query-mutable

1.2、lowbit()操作

  このアルゴリズムを最初に実行するには、最初にツリー配列とは何かを理解する必要があります。

  ツリー配列を理解するには、知っておく必要のある前提知識があります。それは** lowbit()**操作です。lowbit()演算とは何ですか?その概念的な理解は、非負の整数の最下位ビットと、バイナリ表現の背後にある0によって形成される値です。1))のビット単位のANDを反転します。

画像の説明を追加してください

//计算树状数组中的lowbit(x)的值
int lowbit(int x){
    
    
    return x & -x;
}

1.3。思考と実現

c [x]は[x-lowbit(x)+ 1、x]の合計です。ここで、次のシーケンスのグラフを描画します。

画像の説明を追加してください

C[x]の親ノードはC[x+ lowbit(x)]です。

1.4、メソッドのクエリとメソッドの追加

1.4.1、クエリメソッド(間隔クエリ)

C [x]を追加または追加するには、祖先ノードを変更および変更し、x + = lowbit(x)を計算して、親ノードの添え字を取得します。

//树状数组中的query方法
int query(int x){
    
    
    int ans = 0;
    //查询tree[x]节点的前缀
    for(int i = x;i > 0;i -= lowbit(i))
        //计算tree[x]节点的前缀和
        ans += tree[i];
    return ans;
}

1.4.2、メソッドの追加(シングルポイント変更)

C [x]ノードの接頭辞の合計を照会し、ノードから座席までの前のノードを見つけ、x-= lowbit(x)を計算して、前のノードの添え字を取得します。

//树状数组中的add方法
void add(int x,int y){
    
    
    //查询tree[x]节点的祖先节点
    for(int i = x;i <= n;i +=lowbit(i))
        //将tree[x]节点的祖先节点进行更改
        tree[i] += y;
}

1.5、問題解決のアイデア

タイトルでは、実装で特定の位置にある修道女の値を更新する必要があるため、元のnums配列を保存します。

  1. コンストラクター:ツリー配列は最初はゼロシーケンスに対応しているため、nums配列をトラバースし、add関数を呼び出してツリー配列を更新します。
  2. update関数:インデックスでnumsの増分値を取得し、add関数を呼び出してツリー配列を更新し、nums [index]=valを更新します。
  3. sumRange関数:間隔の合計[左、右]は、2つのプレフィックスの合計の差に変換できます。ツリー配列のprefixSum関数を呼び出して、最初の右+ 1要素のプレフィックスの合計とsum1、およびのプレフィックスの合計を取得します。最初の左側の要素。Sum2、sum1-sum2を返します。

1.6。アルゴリズム

class NumArray {
    
    
    //定义一个树状数组
    int [] tree;
    int [] sum;
    int n;

    //计算树状数组中的lowbit(x)的值
    int lowbit(int x){
    
    
        return x & -x;
    }

    //树状数组中的query方法
    int query(int x){
    
    
        int ans = 0;
        //查询tree[x]节点的前缀
        for(int i = x;i > 0;i -= lowbit(i))
            //计算tree[x]节点的前缀和
            ans += tree[i];
        return ans;
    }

    //树状数组中的add方法
    void add(int x,int y){
    
    
        //查询tree[x]节点的祖先节点
        for(int i = x;i <= n;i +=lowbit(i))
            //将tree[x]节点的祖先节点进行更改
            tree[i] += y;
    }

    //用整数数组 nums 初始化对象
    public NumArray(int[] nums) {
    
    
        sum = nums;
        n = sum.length;
        tree = new int[n+1];
        for(int i = 0;i<n;i++)
            add(i + 1,sum[i]);
    }
    
    //将 nums[index] 的值 更新 为 val
    public void update(int index, int val) {
    
    
        add(index + 1,val-sum[index]);
        sum[index] = val;
    }
    
    //返回数组 nums 中索引 left 和索引 right 之间( 包含 )的nums元素的和
    public int sumRange(int left, int right) {
    
    
        return query(right + 1) - query(left);
    }
}

おすすめ

転載: blog.csdn.net/qq_52916408/article/details/123976118