[LeetCode] Range Sum Query - Mutable 区域和检索 - 可变

简介:

Given an integer array nums, find the sum of the elements between indices i and j (i ≤ j), inclusive.

The update(i, val) function modifies nums by updating the element at index i to val.

Example:

Given nums = [1, 3, 5]
sumRange(0, 2) -> 9
update(1, 2)
sumRange(0, 2) -> 8

Note:

  1. The array is only modifiable by the update function.
  2. You may assume the number of calls to update and sumRange function is distributed evenly.

这道题是之前那道Range Sum Query - Immutable 区域和检索 - 不可变的延伸,之前那道题由于数组的内容不会改变,所以我们只需要建立一个累计数组就可以支持快速的计算区间值了,而这道题说数组的内容会改变,如果我们还是用之前的方法建立累计和数组,那么每改变一个数字,之后所有位置的数字都要改变,这样如果有很多更新操作的话,就会十分不高效。这道题我们要使用一种新的数据结构,叫做树状数组Binary Indexed Tree,又称Fenwick Tree,这是一种查询和修改复杂度均为O(logn)的数据结构。这个树状数组比较有意思,所有的奇数位置的数字和原数组对应位置的相同,偶数位置是原数组若干位置之和,假如原数组A(a1, a2, a3, a4 ...),和其对应的树状数组C(c1, c2, c3, c4 ...)有如下关系:

C1 = A1
C2 = A1 + A2
C3 = A3
C4 = A1 + A2 + A3 + A4
C5 = A5
C6 = A5 + A6
C7 = A7
C8 = A1 + A2 + A3 + A4 + A5 + A6 + A7 + A8
...

那么是如何确定某个位置到底是有几个数组成的呢,原来是根据坐标的最低位Low Bit来决定的,所谓的最低位,就是二进制数的最右边的一个1开始,加上后面的0(如果有的话)组成的数字,例如1到8的最低位如下面所示:

坐标          二进制          最低位

1               0001          1

2               0010          2

3               0011          1

4               0100          4

5               0101          1

6               0110          2

7               0111          1

8               1000          8

...

最低位的计算方法有两种,一种是x&(x^(x–1)),另一种是利用补码特性x&-x。

这道题我们先根据给定输入数组建立一个树状数组bit,然后更新某一位数字时,根据最低位的值来更新后面含有这一位数字的地方,一般只需要更新部分偶数位置的值即可,在计算某一位置的前缀和时,利用树状数组的性质也能高效的算出来,参见代码如下:

class NumArray {
public:
    NumArray(vector<int> &nums) {
        num.resize(nums.size() + 1);
        bit.resize(nums.size() + 1);
        for (int i = 0; i < nums.size(); ++i) {
            update(i, nums[i]);
        }
    }
    void update(int i, int val) {
        int diff = val - num[i + 1];
        for (int j = i + 1; j < num.size(); j += (j&-j)) {
            bit[j] += diff;
        }
        num[i + 1] = val;
    }
    int sumRange(int i, int j) {
        return getSum(j + 1) - getSum(i);
    }    
    int getSum(int i) {
        int res = 0;
        for (int j = i; j > 0; j -= (j&-j)) {
            res += bit[j];
        }
        return res;
    }

private:
    vector<int> num;
    vector<int> bit;
};

本文转自博客园Grandyang的博客,原文链接:区域和检索 - 可变[LeetCode] Range Sum Query - Mutable ,如需转载请自行联系原博主。

相关文章
|
7月前
|
索引 Python
leetcode-307:区域和检索 - 数组可修改
leetcode-307:区域和检索 - 数组可修改
40 0
|
7月前
|
JavaScript SoC
leetcode-304:二维区域和检索 - 矩阵不可变
leetcode-304:二维区域和检索 - 矩阵不可变
63 0
|
7月前
|
索引 Python
leetcode-303:区域和检索 - 数组不可变
leetcode-303:区域和检索 - 数组不可变
33 0
|
iOS开发 索引
LeetCode--1773. 统计匹配检索规则的物品数量
给你一个数组 items ,其中 items[i] = [typei, colori, namei] ,描述第 i 件物品的类型、颜色以及名称。 另给你一条由两个字符串 ruleKey 和 ruleValue 表示的检索规则。 如果第 i 件物品能满足下述条件之一,则认为该物品与给定的检索规则 匹配 : ruleKey == "type" 且 ruleValue == typei 。 ruleKey == "color" 且 ruleValue == colori 。 ruleKey == "name" 且 ruleValue == namei 。 统计并返回 匹配检索规则的物品数量 。
85 0
LeetCode 1773. 统计匹配检索规则的物品数量
给你一个数组 items ,其中 items[i] = [typei, colori, namei] ,描述第 i 件物品的类型、颜色以及名称。
102 0
|
索引 Python
LeetCode 303. 区域和检索 - 数组不可变
给定一个整数数组 nums,求出数组从索引 i 到 j(i ≤ j)范围内元素的总和,包含 i、j 两点。
108 0
LeetCode 307. Range Sum Query - Mutable
update(i, val) 函数可以通过将下标为 i 的数值更新为 val,从而对数列进行修改。
108 0
LeetCode 307. Range Sum Query - Mutable
LeetCode 304. Range Sum Query 2D - Immutable
给定一个二维矩阵,计算其子矩形范围内元素的总和,该子矩阵的左上角为 (row1, col1) ,右下角为 (row2, col2)。
108 0
LeetCode 304. Range Sum Query 2D - Immutable
|
索引
LeetCode 303. Range Sum Query - Immutable
给定一个整数数组 nums,求出数组从索引 i 到 j (i ≤ j) 范围内元素的总和,包含 i, j 两点。
97 0
LeetCode 303. Range Sum Query - Immutable
|
3月前
|
Unix Shell Linux
LeetCode刷题 Shell编程四则 | 194. 转置文件 192. 统计词频 193. 有效电话号码 195. 第十行
本文提供了几个Linux shell脚本编程问题的解决方案,包括转置文件内容、统计词频、验证有效电话号码和提取文件的第十行,每个问题都给出了至少一种实现方法。
LeetCode刷题 Shell编程四则 | 194. 转置文件 192. 统计词频 193. 有效电话号码 195. 第十行