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:ide
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) -> 10Note:spa
The matrix is only modifiable by the update function.code
You may assume the number of calls to update and sumRegion function is distributed evenly.圖片
You may assume that row1 ≤ row2 and col1 ≤ col2.element
注意這道題說明了"calls to update and sumRegion function is distributed evenly"
。咱們能夠先不考慮這道題的限制,根據這個兩個方法使用次數分狀況討論:leetcode
update多,sumRegion少
這種狀況比較簡單,咱們能夠直接複製矩陣,update的時候直接update對應點的值便可,sumRegion直接遍歷指定範圍內的值就能夠了。it
update: O(1), sumRegion: O(mn)
update少,sumRegion多。
咱們能夠不復制整個矩陣,而是在每一個點處存(0, 0)到該的長方形內全部元素的和,這樣的話,sumRegion的複雜度會很低,update的時候咱們須要update全部受影響的sum。io
update: O(mn), sumRegion: O(1)
update多,sumRegion多(本題狀況)
咱們能夠每一個點存對於該行,起始點到該點爲止的sum。這樣話,update的話,咱們只須要update該行受影響的sum便可。sumRegion的話,咱們只須要遍歷相應行,加上不一樣行的對應sum便可。table
update: O(n), sumRegion: O(m)
固然,對於這種類型的題目,使用一些高級數據結構會更時間複雜度會更低,能達到logn,如二維線段樹。這裏只涉及基本的數據結構,儘可能不搞複雜。
注:m指行數,n指列數,這裏global的矩陣不算各個方法的extra space。
time: O(n), space: O(1)
time: O(m), space: O(1)
public class NumMatrix { int[][] rowSums; public NumMatrix(int[][] matrix) { if (matrix.length == 0) return; rowSums = new int[matrix.length][matrix[0].length]; // 建rowSums矩陣 for (int i = 0; i < matrix.length; i++) { for (int j = 0; j < matrix[0].length; j++) { rowSums[i][j] = matrix[i][j] + (j == 0 ? 0 : rowSums[i][j - 1]); } } } public void update(int row, int col, int val) { // 求出新值與舊值的差 int diff = val - (rowSums[row][col] - (col == 0 ? 0 : rowSums[row][col - 1])); // 更新該行受影響的sum for (int j = col; j < rowSums[0].length; j++) { rowSums[row][j] += diff; } } public int sumRegion(int row1, int col1, int row2, int col2) { int res = 0; // 逐行求和,每行的相應和爲兩sum相減 for (int i = row1; i <= row2; i++) { res += rowSums[i][col2] - (col1 == 0 ? 0 :rowSums[i][col1 - 1]); } return res; } } // 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);