[
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
matrixas 2D array of dictionaries: for each cell we have valuevaland 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 valuevto 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 edgesEfor 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 ourgetfunction 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), whereEis 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 instrsand create defaultdictm: what cells we need to take with which weights. Complexity isO(WHE) < O(W^2H^2), whereEagain 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)