资讯专栏INFORMATION COLUMN

Range Sum Query

zhongmeizhi / 1058人阅读

摘要:表现在二进制上的规律每次加上最末尾的求末尾的就拿这个数和它的补码于。还有要求不是,要转换一下,和之前那道的思路差不多。这里用一个的表示从到的和。

Range Sum Query - Immutable

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

Example: Given nums = [-2, 0, 3, -5, 2, -1]
sumRange(0, 2) -> 1
sumRange(2, 5) -> -1
sumRange(0, 5) -3

Note:
You may assume that the array does not change.
There are many calls to sumRange function.

用dp解。dp[i]表示sumRange(0, i-1)
function是dp[i+1] = dp[i] + nums[i]
所以sumRange(i, j) = dp[j+1] - dp[i]

public class NumArray {
    int[] dp;
    public NumArray(int[] nums) {
        dp = new int[nums.length + 1];
        for(int i = 0; i < nums.length; i++) {
            dp[i+1] = dp[i] + nums[i];
        }
    }
    
    public int sumRange(int i, int j) {
        return dp[j + 1] - dp[i];
    }
}
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:

The array is only modifiable by the update function.

You may assume the number of calls to update and sumRange function is distributed evenly.

和上一题的区别在于,这次数组里面的值会动态的变化,所以不能和上面一题一样,最开始初始化一个dp数组之后就不管了。如果还是用dp数组,那么每次update之后都得重新再改一遍,O(N)时间复杂度太高。
用binary index tree来做,update和sum的时间复杂度都是O(NlogN)。原理如下:
index: 1------2------3------4------5------6------7-----8-----9
binary: 0001-0010-0011-0100-0101-0110-0111-1000-1001
value: 2------5------6------3------1------7------5-----3-----2

tree[i]: [1,1]--[1,2]--[3,3]--[1,4]--[5,5]--[5,6]--[7,7]--[1,8]--[9,9]

Level1: 2------7------------16------------------------34

Level2: --------------6-------------1-----8-------------------9

right index in level1 has one "1" in binary representation.
right index in level2 has two "1" in binary representation.
......

2个主要的method:add 和 sum
add(idx, val): add val to nums[i]
sum(idx): get the sum from 1 to idx

add的时候改怎么操作呢?
举个例子,比如add(5, 2), 我想在index = 5的地方加2,那么:

start从idx = 5开始,tree[5] += 2

接着,要更新tree[6],也就是sum(5, 6)

再接着更新tree[8],也就是sum(1, 8)

在图里的表现就是我先从start开始,把start同一level所有往右相邻的更新一遍,没有相邻的之后,就往上一面一层走,重复更新的过程。直到idx超过长度。

表现在二进制上的规律:

5 -------> 6 ------> 8

0101 -> 0110 -> 1000

每次加上最末尾的‘1’

0101 + 0001 = 0110

0110 + 0010 = 1000

求末尾的‘1’就拿这个数和它的补码于。
假设这个数是x = n(1,0)-1-m(0)
m(0)表示这个数末尾有m个0,n(1,0)表示这个数前面有n个1或者0。那么第一个1就出现在从右数第m+1位上。

现在求x的反码,~x = ~n(1,0)-0-m(1)

那么x的补码就是:-x = ~n(1,0)-1-m(0)

所以: x&-x = n(0)-1-m(0)

void add(int idx, int val) {
    while(idx < tree.length) {
        tree[idx] += val;
        idx += i & -i;
    }
}
int sum(int idx) {
    int result = 0;
    while(idx > 0) {
        result += tree[idx];
        idx += i & -i;
    }
    return result;
}

sum的方法同理,init的直接用add即可。这道题注意下数组的index是从0开始,所以每次要+1。还有要求update不是add,要转换一下,update(idx, val) = add(idx, val - nums[idx])

public class NumArray {
    // binary index tree
    int[] tree;
    int[] nums;
    public NumArray(int[] nums) {
        this.nums = nums;
        tree = new int[nums.length + 1];
        for(int i = 0; i < nums.length; i++) {
            add(i, nums[i]);
        }
    }
    
    private void add(int i, int val) {
        i += 1;
        while(i < tree.length) {
            tree[i] += val;
            i += i & -i;
        }
    }
    
    public void update(int i, int val) {
        int diff = val - nums[i];
        nums[i] = val;
        add(i, diff);
    }
    
    public int sumRange(int i, int j) {
        return sum(j) - sum(i - 1);
    }
    
    // return the sumRange(0, i)
    private int sum(int i) {
        i+= 1;
        int result = 0;
        while(i > 0) {
            result += tree[i];
            i -= i & -i;
        }
        return result;
    }
}
Range Sum Query 2D - Immutable

Given a 2D matrix matrix, find the sum of the elements inside the rectangle defined by its upper left corner (row1, col1) and lower right corner (row2, col2).

Range Sum Query 2D

The above rectangle (with the red border) is defined by (row1, col1) = (2, 1) and (row2, col2) = (4, 3), which contains sum = 8.

Example:
Given matrix = [
[3, 0, 1, 4, 2],
[5, 6, 3, 2, 1],
[1, 2, 0, 1, 5],
[4, 1, 0, 1, 7],
[1, 0, 3, 0, 5] ]

sumRegion(2, 1, 4, 3) -> 8
sumRegion(1, 1, 2, 2) -> 11
sumRegion(1, 2, 2, 4) -> 12
Note:
You may assume that the matrix does not change.
There are many calls to sumRegion function. You may assume that row1 ≤ row2 and col1 ≤ col2.

和之前那道1d的思路差不多。这里用一个2d的prefix array:
dp[i + 1] [j + 1] 表示从 [0, 0] 到 [i, j] 的和。function是:
dp[i + 1] [j + 1] = dp[i + 1] [j] + dp[i] [j + 1] - dp[i] [j] + matrix[i] [j]
所以sum(row1, col1, row2, col2) = dp[row2 + 1] [col2 + 1] - dp[row1] [col2 + 1] - dp[row2 + 1] [col1] + dp[row1] [col1]

public class NumMatrix {
    // dp
    int[][] dp;
    public NumMatrix(int[][] matrix) {
        if(matrix == null || matrix.length == 0 || matrix[0] == null || matrix[0].length == 0) return;
        dp = new int[matrix.length + 1][matrix[0].length + 1];
        for(int i = 0; i < matrix.length; i++) {
            for(int j = 0; j < matrix[0].length; j++) {
                dp[i+1][j+1] = dp[i+1][j] + dp[i][j+1] - dp[i][j] + matrix[i][j];
            }
        }
    }
    
    public int sumRegion(int row1, int col1, int row2, int col2) {
        return dp[row2 + 1][col2 + 1] - dp[row1][col2 + 1] - dp[row2 + 1][col1] + dp[row1][col1];
    }
}
Range Sum Query 2D - Mutable

Given a 2D matrix matrix, find the sum of the elements inside the rectangle defined by its upper left corner (row1, col1) and lower right corner (row2, col2).

Range Sum Query 2D
The above rectangle (with the red border) is defined by (row1, col1) = (2, 1) and (row2, col2) = (4, 3), which contains sum = 8.

Example:
Given matrix = [
[3, 0, 1, 4, 2],
[5, 6, 3, 2, 1],
[1, 2, 0, 1, 5],
[4, 1, 0, 1, 7],
[1, 0, 3, 0, 5]
]

sumRegion(2, 1, 4, 3) -> 8
update(3, 2, 2)
sumRegion(2, 1, 4, 3) -> 10

Note:

The matrix is only modifiable by the update function.

You may assume the number of calls to update and sumRegion function is distributed evenly.

You may assume that row1 ≤ row2 and col1 ≤ col2.

和1d的mutable的差不多。还是用binary index tree来做。时间还是都是O(NlogN)。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/66563.html

相关文章

  • leetcode303-304 Range Sum Query Immutable

    摘要:假设有一个整数数组,计算下标从到包含和的数字的和。求和的请求将会在同一个整数数组上多次请求。这一题思路很简单,因为。而利用动态规划则很容易知道。这里将原先的一维数组替换成二维数组。要求计算一个矩形内的所有元素的值。 Range Sum Query Immutable Given an integer array nums, find the sum of the elements be...

    Worktile 评论0 收藏0
  • leetcode307. Range Sum Query - Mutable

    摘要:题目要求可以先参考数组不发生变动时的题目。最后的叶节点为当前数组的值,非叶结点则记录了子数组的范围以及该子数组中所有元素的和。它是一个非常轻量级的数据结构,而且几乎就是为这种题目量身打造。 题目要求 Given an integer array nums, find the sum of the elements between indices i and j (i ≤ j), inc...

    Lemon_95 评论0 收藏0
  • [LeetCode] 304. Range Sum Query 2D - Immutable

    Problem Given a 2D matrix matrix, find the sum of the elements inside the rectangle defined by its upper left corner (row1, col1) and lower right corner (row2, col2). https://leetcode.com/static/i...s...

    chinafgj 评论0 收藏0
  • [LeetCode] Range Sum Query Immutable

    Problem Given an integer array nums, find the sum of the elements between indices i and j (i ≤ j), inclusive. Example Given nums = [-2, 0, 3, -5, 2, -1] sumRange(0, 2) -> 1 sumRange(2, 5) -> -1 sumRan...

    LiuZh 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<