LeetCode题解(0631):设计Excel求和公式(Python)

题目:原题链接(困难)

标签:设计、图、拓扑排序

解法时间复杂度空间复杂度执行用时
Ans 1 (Python)SET = O ( H × W ) O(H×W) O(H×W) ; GET = O ( 1 ) O(1) O(1) ; SUM = O ( H × W × S ) O(H×W×S) O(H×W×S) O ( H × W ) O(H×W) O(H×W)36ms (92.00%)
Ans 2 (Python)
Ans 3 (Python)

解法一:

class Excel:

    def __init__(self, h: int, w: str):
        self.h = h
        self.w = self._get_col(w) + 1
        self.table = [[0] * self.w for _ in range(self.h)]
        self.formula = {}  # 公式列表(用于删除公式时使用)

        self.graph = collections.defaultdict(collections.Counter)  # 单元格关系图(用于更新值时使用)

    def set(self, r: int, c: str, v: int) -> None:
        r -= 1
        c = self._get_col(c)
        # print("[SET]", (r, c), "->", v)
        if 0 <= r < self.h and 0 <= c < self.w:
            self._update(r, c, v - self.table[r][c])  # 更新单元格的值,并更新所有引用了这个单元格的值
            self._remove(r, c)  # 移除单元格中的公式和单元格关系

    def get(self, r: int, c: str) -> int:
        r -= 1
        c = self._get_col(c)
        return self.table[r][c]

    def sum(self, r: int, c: str, strs: List[str]) -> int:
        r -= 1
        c = self._get_col(c)
        # print("[SUM]", (r, c), "->", strs)
        self.formula[(r, c)] = collections.Counter()  # 引用的单元格列表
        self.table[r][c] = 0
        for s in strs:
            if ":" not in s:
                r1, c1 = int(s[1:]) - 1, self._get_col(s[0])
                # print("[SUM]", (r, c), "<-", (r1, c1))
                self.formula[(r, c)][(r1, c1)] += 1  # 记录公式关系
                self.table[r][c] += self.table[r1][c1]  # 计算当前位置的值
                self.graph[(r1, c1)][(r, c)] += 1  # 更新单元格关系图
            else:
                s1, s2 = s.split(":")
                r1, c1 = int(s1[1:]) - 1, self._get_col(s1[0])
                r2, c2 = int(s2[1:]) - 1, self._get_col(s2[0])
                # print("[SUM]", s, "->", (r1, c1), (r2, c2))
                for r3 in range(r1, r2 + 1):
                    for c3 in range(c1, c2 + 1):
                        # print("[SUM]", (r, c), "<-", (r3, c3))
                        self.formula[(r, c)][(r3, c3)] += 1  # 记录公式关系
                        self.table[r][c] += self.table[r3][c3]  # 计算当前位置的值
                        self.graph[(r3, c3)][(r, c)] += 1  # 更新单元格关系图
        return self.table[r][c]

    def _remove(self, r: int, c: int) -> None:
        """移除单元格中的公式和单元格关系"""
        if (r, c) in self.formula:
            for r1, c1 in self.formula[(r, c)]:
                del self.graph[(r1, c1)][(r, c)]
            del self.formula[(r, c)]

    def _update(self, r: int, c: int, v: int) -> None:
        """更新单元格的值,并更新所有引用了这个单元格的值"""
        queue = collections.deque([(r, c, 1)])
        while queue:
            (r1, c1, t1) = queue.popleft()
            self.table[r1][c1] += v * t1
            # print("[UPDATE]", (r, c), "->", (r1, c1), "=", v * t1)
            if (r1, c1) in self.graph:
                for (r2, c2) in self.graph[(r1, c1)]:
                    queue.append((r2, c2, t1 * self.graph[(r1, c1)][(r2, c2)]))

    @staticmethod
    def _get_col(s: str) -> int:
        """依据列名计算列号"""
        ans = 0
        for i in range(len(s)):
            ans += (ord(s[-(i + 1)]) - 64) * pow(26, i)
        return ans - 1
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

长行

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值