博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Range Sum Query
阅读量:7194 次
发布时间:2019-06-29

本文共 5985 字,大约阅读时间需要 19 分钟。

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:

  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.

和上一题的区别在于,这次数组里面的值会动态的变化,所以不能和上面一题一样,最开始初始化一个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位上。

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

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

  3. 所以: 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:

  1. The matrix is only modifiable by the update function.

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

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

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

转载地址:http://lkxkm.baihongyu.com/

你可能感兴趣的文章
iPad中国内地商标权诉讼调查
查看>>
[UIKit学习]05.关于plist
查看>>
JPEG-LS extensions标准
查看>>
【1171】C语言实验——保留整数 (栈)SDUT
查看>>
SQLite查询记录总数
查看>>
聚类算法优秀博客链接
查看>>
php 事物处理
查看>>
android 手机拍照返回 Intent==null 以及intent.getData==null
查看>>
从远程服务器上下载图片代码
查看>>
C#和JavaScript交互(asp.net前台和后台互调)总结 (转)
查看>>
[转]Android Binder设计与实现 - 设计篇
查看>>
都9102年了,还在给磁盘分区?
查看>>
python第十二周:MySql
查看>>
2019亚洲物联网安全创新国际峰会将于5月在上海开幕!
查看>>
C#反射的实现
查看>>
【想法】滴滴更新迭代功能
查看>>
aircrack-ng破解WiFi密码
查看>>
iOS设备中WiFi、蓝牙和飞行模式的开启与关闭
查看>>
事务传播行为和特性
查看>>
[Ting's笔记Day3]解决Git常见错误non-fast-forward问题
查看>>