-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathrange-sum-query-2d-immutable.py
More file actions
84 lines (65 loc) · 3.19 KB
/
range-sum-query-2d-immutable.py
File metadata and controls
84 lines (65 loc) · 3.19 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
# https://leetcode.com/problems/range-sum-query-2d-immutable/
# Related Topics: Dynamic Programming
# Difficulty: Medium
# Initial thoughts:
# The naive approach is to look at each and every element every time
# and sum them. This would have a Time Complexity of O(n) and a Space Complexity of O(1)
# Optimization:
# Using a Dynamic Programming approach, we can create a suplemental matrix where each element
# contains the sum of all the values before it in that specific row plus itself.
# Now to find the sum of the elements in a box in the matrix we need to add the sums for each
# row in that box.
# This is very similar to range-sum-query-immutable.py and its solution and will only add another
# dimension to the whole problem.
# Preprocessing will take up O(n) where n === matrix.width * matrix.heigth
# Lookup time for a box inside the matrix is O(matrix.height) since the sum of a row can be calculated
# in constant time.
# Time complexity: O(n) where n === matrix.width * matrix.heigth
# Space complexity: O(n) where n === matrix.width * matrix.heigth
from typing import List
class NumMatrix:
def __init__(self, matrix: List[List[int]]):
self._matrix = matrix
self._dp = self.preprocess()
def sumRegion(self, row1: int, col1: int, row2: int, col2: int) -> int:
sum = 0
for i in range(row1, row2+1):
sum += self._dp[i][col2+1] - self._dp[i][col1]
return sum
def preprocess(self) -> List[List[int]]:
dp = [[0 for i in range(len(self._matrix[0])+1)]
for j in range(len(self._matrix))]
for i in range(len(self._matrix)):
for j in range(len(self._matrix[0])):
dp[i][j+1] = dp[i][j] + self._matrix[i][j]
return dp
def sumRegionNaive(self, row1: int, col1: int, row2: int, col2: int) -> int:
sum = 0
for i in range(row1, row2+1):
for j in range(col1, col2+1):
sum += self._matrix[i][j]
return sum
# Optimization:
# We could render the lookup time constant by storing the sum of the whole box before an element
# in the dp array. Then with some basic arithmetic we can calculate any box in the matrix.
# Time Complexity: O(n) where n === matrix.width * matrix.heigth
# Space Complexity: O(n) where n === matrix.width * matrix.heigth
class NumMatrix:
def __init__(self, matrix: List[List[int]]):
self._matrix = matrix
self._dp = self.preprocess()
def sumRegion(self, row1: int, col1: int, row2: int, col2: int) -> int:
return self._dp[row2+1][col2+1] - self._dp[row1][col2+1] - self._dp[row2+1][col1] + self._dp[row1][col1]
def preprocess(self):
if len(self._matrix) == 0 or len(self._matrix[0]) == 0:
return None
dp = [[0 for i in range(len(self._matrix[0])+1)]
for j in range(len(self._matrix)+1)]
for i in range(len(self._matrix)):
for j in range(len(self._matrix[0])):
dp[i+1][j+1] = dp[i+1][j] + dp[i][j+1] - \
dp[i][j] + self._matrix[i][j]
return dp
# Your NumMatrix object will be instantiated and called as such:
# obj = NumMatrix(matrix)
# param_1 = obj.sumRegion(row1,col1,row2,col2)