题目:

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).


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.

链接: http://leetcode.com/problems/range-sum-query-2d-mutable/

题解:

二维Range Sum Query mutable,我了个去,第一次Leetcode写了超过140行代码...足够臭长了吧,但是居然能ac,还是很高兴 -____-!! 原理是要构建一个2D Segment Tree或者 2D Fenwick Tree。由于上一题是先做的Segment Tree,这回也先写2D Segment Tree。构建2D Segment Tree依然是使用Divide and Conquer,我们要把整个平面分成4个部分,所以2D Segment Tree也是一个Quad Tree,每个节点有四个子节点,NW, NE, SW, SE, 节点的sum是四个子节点的sum。这样我们就可以用与1D Segment Tree类似的方法来写rangeSum以及update。要注意rangeSum时的判断,有好几种情况,比较复杂。

2D Segment Tree: Time Complexity - O(mn) build,O(logmn) update, O(logmn) rangeSum , Space Complexity - O(mn)  复杂度算得不是很清楚,很可能不正确,二刷再继续改正。

public class NumMatrix {
private class SegmentTreeNode2D {
public int tlRow;
public int tlCol;
public int brRow;
public int brCol;
public int sum;
public SegmentTreeNode2D nw, ne, sw, se; public SegmentTreeNode2D(int tlRow, int tlCol, int brRow, int brCol) {
this.tlRow = tlRow;
this.tlCol = tlCol;
this.brRow = brRow;
this.brCol = brCol;
this.sum = 0;
}
} public SegmentTreeNode2D root; public NumMatrix(int[][] matrix) {
if(matrix == null || matrix.length == 0) {
return;
}
root = buildTree(matrix, 0, 0, matrix.length - 1, matrix[0].length - 1);
} public void update(int row, int col, int val) {
update(root, row, col, val);
} private void update(SegmentTreeNode2D node, int row, int col, int val) {
if(node.tlRow == row && node.brRow == row && node.tlCol == col && node.brCol == col) {
node.sum = val;
return;
}
int rowMid = node.tlRow + (node.brRow - node.tlRow) / 2;
int colMid = node.tlCol + (node.brCol - node.tlCol) / 2;
if(row <= rowMid) {
if(col <= colMid) {
update(node.nw, row, col, val);
} else {
update(node.ne, row, col, val);
}
} else {
if(col <= colMid) {
update(node.sw, row, col, val);
} else {
update(node.se, row, col, val);
}
} node.sum = 0;
if(node.nw != null) {
node.sum += node.nw.sum;
}
if(node.ne != null) {
node.sum += node.ne.sum;
}
if(node.sw != null) {
node.sum += node.sw.sum;
}
if(node.se != null) {
node.sum += node.se.sum;
}
} public int sumRegion(int row1, int col1, int row2, int col2) {
return sumRegion(root, row1, col1, row2, col2);
} private int sumRegion(SegmentTreeNode2D node, int tlRow, int tlCol, int brRow, int brCol) {
if(node.tlRow == tlRow && node.tlCol == tlCol && node.brRow == brRow && node.brCol == brCol) {
return node.sum;
}
int rowMid = node.tlRow + (node.brRow - node.tlRow) / 2;
int colMid = node.tlCol + (node.brCol - node.tlCol) / 2;
if(brRow <= rowMid) { // top-half plane
if(brCol <= colMid) { // north-west quadrant
return sumRegion(node.nw, tlRow, tlCol, brRow, brCol);
} else if(tlCol > colMid) { // north-east quadrant
return sumRegion(node.ne, tlRow, tlCol, brRow, brCol);
} else { // intersection between nw and ne
return sumRegion(node.nw, tlRow, tlCol, brRow, colMid) + sumRegion(node.ne, tlRow, colMid + 1, brRow, brCol);
}
} else if(tlRow > rowMid) { // bot-half plane
if(brCol <= colMid) { // south-west quadrant
return sumRegion(node.sw, tlRow, tlCol, brRow, brCol);
} else if(tlCol > colMid) { // south-east quadrant
return sumRegion(node.se, tlRow, tlCol, brRow, brCol);
} else { //intersection between sw and sw
return sumRegion(node.sw, tlRow, tlCol, brRow, colMid) + sumRegion(node.se, tlRow, colMid + 1, brRow, brCol);
}
} else { // full-plane intersection
if(brCol <= colMid) { // left half plane
return sumRegion(node.nw, tlRow, tlCol, rowMid, brCol) + sumRegion(node.sw, rowMid + 1, tlCol, brRow, brCol) ;
} else if(tlCol > colMid) { // right half plane
return sumRegion(node.ne, tlRow, tlCol, rowMid, brCol) + sumRegion(node.se, rowMid + 1, tlCol, brRow, brCol) ;
} else { // full-plane intersection
return sumRegion(node.nw, tlRow, tlCol, rowMid, colMid)
+ sumRegion(node.ne, tlRow, colMid + 1, rowMid, brCol)
+ sumRegion(node.sw, rowMid + 1, tlCol, brRow, colMid)
+ sumRegion(node.se, rowMid + 1, colMid + 1, brRow, brCol);
}
}
} private SegmentTreeNode2D buildTree(int[][] matrix, int tlRow, int tlCol, int brRow, int brCol) {
if(tlRow > brRow || tlCol > brCol) {
return null;
} else {
SegmentTreeNode2D node = new SegmentTreeNode2D(tlRow, tlCol, brRow, brCol);
if(tlRow == brRow && tlCol == brCol) {
node.sum = matrix[tlRow][tlCol];
} else {
int rowMid = tlRow + (brRow - tlRow) / 2;
int colMid = tlCol + (brCol - tlCol) / 2;
node.nw = buildTree(matrix, tlRow, tlCol, rowMid, colMid);
node.ne = buildTree(matrix, tlRow, colMid + 1, rowMid, brCol);
node.sw = buildTree(matrix, rowMid + 1, tlCol, brRow, colMid);
node.se = buildTree(matrix, rowMid + 1, colMid + 1, brRow, brCol);
node.sum = 0;
if(node.nw != null) {
node.sum += node.nw.sum;
}
if(node.ne != null) {
node.sum += node.ne.sum;
}
if(node.sw != null) {
node.sum += node.sw.sum;
}
if(node.se != null) {
node.sum += node.se.sum;
}
}
return node;
}
}
} // Your NumMatrix object will be instantiated and called as such:
// NumMatrix numMatrix = new NumMatrix(matrix);
// numMatrix.sumRegion(0, 1, 2, 3);
// numMatrix.update(1, 1, 10);
// numMatrix.sumRegion(1, 2, 3, 4);

2D Fenwick Tree:  -- 看了Quora一个acm大神的post以后,我决定还是要使用2D Fenwick Tree来做这题。 “https://www.quora.com/How-does-a-2D-segment-tree-work” ,代码肯定比Segment Tree简洁,而且速度也会更快。基本方法和1D非常类似,这种方法甚至可以简单地扩展到更高维度。

Time Complexity - O(mnlogm * logn) build,  O(logmn) update, O(logmn) rangeSum, Space Complexity - O(mn)

public class NumMatrix {
private int BIT2D[][];
private int matrix[][]; public NumMatrix(int[][] matrix) {
if(matrix == null || matrix.length == 0) {
return;
}
BIT2D = new int[matrix.length + 1][matrix[0].length + 1];
this.matrix = new int[matrix.length][matrix[0].length];
for(int i = 0; i < matrix.length; i++) {
for(int j = 0; j < matrix[0].length; j++) {
update(i, j, matrix[i][j]);
}
}
} public void update(int row, int col, int val) {
int delta = val - matrix[row][col];
matrix[row][col] = val;
for(int i = row + 1; i < BIT2D.length; i += i & (-i)) { //also equals to i |= i + 1
for(int j = col + 1; j < BIT2D[0].length; j += j & (-j)) {
BIT2D[i][j] += delta;
}
}
} public int sumRegion(int row1, int col1, int row2, int col2) {
return getSum(row2 + 1, col2 + 1) - getSum(row1, col2 + 1) - getSum(row2 + 1, col1) + getSum(row1, col1);
} private int getSum(int row, int col) {
int sum = 0;
for(int i = row; i > 0; i -= i & (-i)) {
for(int j = col; j > 0; j -= j & (-j)) {
sum += BIT2D[i][j];
}
}
return sum;
}
} // Your NumMatrix object will be instantiated and called as such:
// NumMatrix numMatrix = new NumMatrix(matrix);
// numMatrix.sumRegion(0, 1, 2, 3);
// numMatrix.update(1, 1, 10);
// numMatrix.sumRegion(1, 2, 3, 4);

Reference:

https://stackoverflow.com/questions/25121878/2d-segment-quad-tree-explanation-with-c/25122078#25122078

https://sites.google.com/site/indy256/algo/fenwick_tree_2d
http://www.hawstein.com/posts/binary-indexed-trees.html
https://www.topcoder.com/community/data-science/data-science-tutorials/binary-indexed-trees/
http://www.wohenniu.com/thread-872-1-1.html
http://bookshadow.com/leetcode/
http://cs.nyu.edu/courses/spring14/CSCI-UA.0480-004/
https://web.stanford.edu/class/cs97si/03-data-structures.pdf
http://stackoverflow.com/questions/9452701/ukkonens-suffix-tree-algorithm-in-plain-english

https://leetcode.com/discuss/71025/segmentation-tree-736ms-indexed-tree-492ms-based-solutions

https://leetcode.com/discuss/70992/c-solution-using-2d-binary-index-tree-easy-to-understand

https://leetcode.com/discuss/72685/share-my-java-2-d-binary-indexed-tree-solution

https://leetcode.com/discuss/71046/java-2d-binary-indexed-tree-solution-80ms

https://leetcode.com/discuss/70948/15ms-easy-to-understand-java-solution

https://leetcode.com/discuss/71169/java-2d-binary-indexed-tree-solution-clean-and-short-17ms

https://leetcode.com/problems/range-sum-query-2d-mutable/

http://www.lxway.com/5152462.htm

https://www.topcoder.com/community/data-science/data-science-tutorials/binary-indexed-trees/

308. Range Sum Query 2D - Mutable的更多相关文章

  1. LeetCode 308. Range Sum Query 2D - Mutable

    原题链接在这里:https://leetcode.com/problems/range-sum-query-2d-mutable/ 题目: Given a 2D matrix matrix, find ...

  2. Range Sum Query 2D - Mutable & Immutable

    Range Sum Query 2D - Mutable Given a 2D matrix matrix, find the sum of the elements inside the recta ...

  3. [Locked] Range Sum Query 2D - Mutable

    Range Sum Query 2D - Mutable Given a 2D matrix matrix, find the sum of the elements inside the recta ...

  4. [LeetCode] Range Sum Query 2D - Mutable 二维区域和检索 - 可变

    Given a 2D matrix matrix, find the sum of the elements inside the rectangle defined by its upper lef ...

  5. Leetcode: Range Sum Query 2D - Mutable && Summary: Binary Indexed Tree

    Given a 2D matrix matrix, find the sum of the elements inside the rectangle defined by its upper lef ...

  6. LeetCode Range Sum Query 2D - Mutable

    原题链接在这里:https://leetcode.com/problems/range-sum-query-2d-mutable/ 题目: Given a 2D matrix matrix, find ...

  7. [Swift]LeetCode308. 二维区域和检索 - 可变 $ Range Sum Query 2D - Mutable

    Given a 2D matrix matrix, find the sum of the elements inside the rectangle defined by its upper lef ...

  8. [LeetCode] Range Sum Query 2D - Immutable 二维区域和检索 - 不可变

    Given a 2D matrix matrix, find the sum of the elements inside the rectangle defined by its upper lef ...

  9. [LeetCode] Range Sum Query - Immutable & Range Sum Query 2D - Immutable

    Range Sum Query - Immutable Given an integer array nums, find the sum of the elements between indice ...

随机推荐

  1. JSON WEB TOKENS

    用JWT来保护我们的ASP.NET Core Web API   在上一篇博客中,自己动手写了一个Middleware来处理API的授权验证,现在就采用另外一种方式来处理这个授权验证的问题,毕竟现在也 ...

  2. 仿照CREATE_FUNC实现CCLayer中的返回CCScene* 的静态函数,宏包装成CREATE_SCENE(XXLayer)

    #define CREATE_SCENE(__TYPE__)\ CCScene *scene()\ { CCScene *scene=CCScene::create();\ __TYPE__ *lay ...

  3. How to check if NSString begins with a certain character

    How to check if NSString begins with a certain character How do you check if an NSString begins with ...

  4. 20145105 《Java程序设计》第2周学习总结

    20145105 <Java程序设计>第2周学习总结 教材学习内容总结 第三章主要的学习内容与c语言有很多相似的地方,讲述了Java的基本语法.其中涵盖: 1. 类型: - short整数 ...

  5. 四则运算2扩展---c++

    题目:让程序能接受用户输入答案,并判定对错.最后给出总共对/错 的数量. 一.设计思想 1.存储用户输入答案,与正确答案比较得出总共对错数量. 二.源程序代码 #include<iostream ...

  6. hdu 3061 Battle 最大权闭合图

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3061 由于小白同学近期习武十分刻苦,很快被晋升为天策军的统帅.而他上任的第一天,就面对了一场极其困难的 ...

  7. iOS开发之runtime的运用-获取当前网络状态

    之前写过runtime的一些东西,这次通过runtime获取一些苹果官方不想让你拿到的东西,比如,状态栏内部的控件属性.本文将通过runtime带你一步步拿到状态栏中显示网络状态的控件,然后通过监测该 ...

  8. [百度空间] [原] Empty base class optimization

    最近遇到了一个诡异的问题, 数组的数据不对, 最后发现是两个类型的大小不一样导致的. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 ...

  9. iis7/7.5设置上传文件最大大小

    本编今天接到一个客户的修改,说一个68M的pdf文件上传不上去,但是我本地开启断点调试了好几遍,都没有问题,能正常上传文件,由此确定不是代码问题.然后我试着上传5M左右的pdf却能正常的上传,然后上传 ...

  10. WinInet:HTTPS 请求出现无效的证书颁发机构的处理

    首先,微软提供的WinInet库封装了对网页访问的方法. 最近工作需要从https服务器获取数据,都知道https和http网页的访问方式不同,多了一道证书认证程序,这样就使得https在请求起来比h ...