###### tags: `Leetcode` `medium` `design` `prefix sum` `python` `c++` # 304. Range Sum Query 2D - Immutable ## [題目連結:] https://leetcode.com/problems/range-sum-query-2d-immutable/ ## 題目: Given a 2D matrix ```matrix```, handle multiple queries of the following type: * Calculate the **sum** of the elements of ```matrix``` inside the rectangle defined by its **upper left corner** ```(row1, col1)``` and **lower right corner** ```(row2, col2)```. Implement the ```NumMatrix``` class: * ```NumMatrix(int[][] matrix)``` Initializes the object with the integer matrix matrix. * ```int sumRegion(int row1, int col1, int row2, int col2)``` Returns the **sum** of the elements of ```matrix``` inside the rectangle defined by its **upper left corner** ```(row1, col1)``` and **lower right corner** ```(row2, col2)```. You must design an algorithm where sumRegion works on ```O(1)``` time complexity. ![](https://i.imgur.com/aIyYd2u.png) ## 解題想法: * 此題為給一矩陣,設計sumRegion函式為,給定範圍,則求出該範圍內的數字和 * 利用prefix sum概念: * 預先計算從左上到右下的所有和,對於索求範圍,扣掉其他範圍 * 示意圖: * 初始: * 將左邊與上邊多一層0 * 計算prefix sum(右邊括號處) * 該格=左+上-左上+matrix中該格的值 * 若求藍色部分: * 黑熱部分-黃色部分+重疊 * 即為prefix中: * 右下(36)扣掉左邊(17)扣掉上面(10),加回重複的(3) = 12 ![](https://i.imgur.com/7H12IKc.png) * 對於最後求解範圍: * row1,col1,row2,col2之判斷 ![](https://i.imgur.com/wqEghRd.png) ## Python: ``` python= class NumMatrix(object): def __init__(self, matrix): """ :type matrix: List[List[int]] """ m=len(matrix) n=len(matrix[0]) #創一個m+1 * n+1的matrix #並將matrix[i][i]存入sum[i+1]sum[j+1] 對齊右下 #sum[i][j]為從matrix[0][0]累加到matrix[i-1][j-1] self.sum=[[0]*(n+1) for _ in range(m+1)] for i in range(1,m+1): for j in range(1,n+1): #左+上-重複的+當前matrix格的值 self.sum[i][j]=self.sum[i-1][j]+self.sum[i][j-1]-self.sum[i-1][j-1]+matrix[i-1][j-1] def sumRegion(self, row1, col1, row2, col2): """ :type row1: int :type col1: int :type row2: int :type col2: int :rtype: int """ #扣掉左邊 上面 加回重複扣到的左上 return self.sum[row2+1][col2+1]-self.sum[row2+1][col1]-self.sum[row1][col2+1]+self.sum[row1][col1] # Your NumMatrix object will be instantiated and called as such: # obj = NumMatrix(matrix) # param_1 = obj.sumRegion(row1,col1,row2,col2) result=NumMatrix([[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]]) ans=result.sumRegion(2, 1, 4, 3) print(ans) ``` ## C++: ``` cpp= class NumMatrix { public: NumMatrix(vector<vector<int>>& matrix) { int m=matrix.size(); int n=matrix[0].size(); //init dp= vector<vector<int>>(m+1, vector<int>(n+1, 0)); for (int i=1; i<m+1; i++){ for (int j=1; j<n+1; j++){ dp[i][j]=dp[i-1][j]+dp[i][j-1]-dp[i-1][j-1]+matrix[i-1][j-1]; } } } int sumRegion(int row1, int col1, int row2, int col2) { return dp[row2+1][col2+1]-dp[row2+1][col1]-dp[row1][col2+1]+dp[row1][col1]; } private: vector<vector<int>> dp; }; /** * Your NumMatrix object will be instantiated and called as such: * NumMatrix* obj = new NumMatrix(matrix); * int param_1 = obj->sumRegion(row1,col1,row2,col2); */ ```