[
graph
topological sort
recursion
]
Leetcode 0631 Design Excel Sum Formula
Problem statement
https://leetcode.com/problems/design-excel-sum-formula/
Solution
The idea is that our Excel table actually is DAG, that is graph without cycles.
- We initialize our
matrix
as 2D array of dictionaries: for each cell we have valueval
and edgesE
: our connections with other cells with weights (we need weights, because we can have something likeA3 = 2A2 + 3B1
). Time complexity isO(WH)
. set(r, c, v)
function just put valuev
to corresponding cell and make connections empty, it is important: “this sum formula should exist until this cell is overlapped by another value or another sum formula”. Time complexity isO(1)
.get(r, c)
. Here we need to check if corresponding edgesE
for this cell is empty. If it is, it means that we reached leaf in our tree and we just return value. If edges are not empty, we need to recursively call ourget
function for all children and sum it. Time complexity is potentiallyO(W^2H^2)
, because we can have fully one-directional connected graph. More precisely, it isO(WHE)
, whereE
is current number of edges in our graph.sum(r, c, strs)
function: here we need to construct connections in our graph: first, we need to process each element instrs
and create defaultdictm
: what cells we need to take with which weights. Complexity isO(WHE) < O(W^2H^2)
, whereE
again is number of edges in our graph.
Complexity
Space complexity is O(WHE) < O(W^2H^2)
, time complexities explained previously.
Code
class Excel:
def __init__(self, H, W):
self.matrix=[[{"val":0, "E": None} for _ in range(ord(W) - 64)] for _ in range(H)]
def set(self, r, c, v):
self.matrix[r-1][ord(c) - 65] = {"val":v, "E":None}
def get(self, r, c):
cell = self.matrix[r - 1][ord(c) - 65]
if not cell["E"]: return cell["val"]
return sum([cell["E"][k]*self.get(k[0] + 1, chr(k[1] + 65)) for k in cell["E"]])
def sum(self, r, c, strs):
m = defaultdict(int)
for s in strs:
l = s.split(':')
i1, j1 = int(l[0][1:]) - 1, ord(l[0][0]) - 65
i2 = i1 if len(l) == 1 else int(l[1][1:]) - 1
j2 = j1 if len(l) == 1 else ord(l[1][0]) - 65
for i in range(i1, i2+1):
for j in range(j1, j2+1):
m[i, j] += 1
self.matrix[r - 1][ord(c) - 65] = {"val":0, "E":m}
return self.get(r, c)