设计 Excel 求和公式

Submission

运行时间: 29 ms

内存: 16.2 MB

class Excel:
    def __init__(self, height: int, width: str):
        self.matrix = [[0] * (ord(width) - ord('A') + 1) for _ in range(height)]
        self.formulas = {}

    def set(self, row: int, column: str, val: int) -> None:
        col_index = ord(column) - ord('A')
        self.matrix[row - 1][col_index] = val
        if (row, column) in self.formulas:
            del self.formulas[(row, column)]

    def get(self, row: int, column: str) -> int:
        col_index = ord(column) - ord('A')
        if (row, column) in self.formulas:
            return self.evaluate_formula(row, column)
        return self.matrix[row - 1][col_index]

    def sum(self, row: int, column: str, numbers: List[str]) -> int:
        col_index = ord(column) - ord('A')
        self.matrix[row - 1][col_index] = sum(self.get_cell_value(num) for num in numbers)
        self.formulas[(row, column)] = numbers
        return self.matrix[row - 1][col_index]

    def get_cell_value(self, cell: str) -> int:
        if ':' in cell:
            start, end = cell.split(':')
            start_row, start_col = int(start[1:]), start[0]
            end_row, end_col = int(end[1:]), end[0]
            total = 0
            for r in range(start_row - 1, end_row):
                for c in range(ord(start_col) - ord('A'), ord(end_col) - ord('A') + 1):
                    total += self.get(r + 1, chr(c + ord('A')))
            return total
        else:
            row, col = int(cell[1:]), cell[0]
            return self.get(row, col)

    def evaluate_formula(self, row: int, column: str) -> int:
        formula = self.formulas[(row, column)]
        return sum(self.get_cell_value(num) for num in formula)

Explain

这个题解实现了一个简化版的Excel,支持设置单元格的值、获取单元格的值以及计算求和公式。主要思路如下: 1. 使用一个二维列表 `matrix` 来存储Excel表格中每个单元格的值。 2. 使用一个字典 `formulas` 来存储每个单元格的求和公式。 3. `set` 方法用于设置单元格的值,同时删除该单元格的求和公式(如果存在)。 4. `get` 方法用于获取单元格的值,如果该单元格有求和公式,则计算求和公式的结果。 5. `sum` 方法用于计算单元格的求和公式,将求和结果存储到对应单元格,并将求和公式存储到 `formulas` 中。 6. `get_cell_value` 方法用于获取单个单元格或单元格范围的值。 7. `evaluate_formula` 方法用于计算单元格的求和公式的结果。

时间复杂度: O(nm)

空间复杂度: O(nm)

```python
class Excel:
    def __init__(self, height: int, width: str):
        # 初始化Excel表格,使用二维列表存储单元格的值
        self.matrix = [[0] * (ord(width) - ord('A') + 1) for _ in range(height)]
        # 使用字典存储单元格的求和公式
        self.formulas = {}

    def set(self, row: int, column: str, val: int) -> None:
        # 将列号转换为索引
        col_index = ord(column) - ord('A')
        # 设置单元格的值
        self.matrix[row - 1][col_index] = val
        # 如果单元格有求和公式,删除求和公式
        if (row, column) in self.formulas:
            del self.formulas[(row, column)]

    def get(self, row: int, column: str) -> int:
        # 将列号转换为索引
        col_index = ord(column) - ord('A')
        # 如果单元格有求和公式,计算求和公式的结果
        if (row, column) in self.formulas:
            return self.evaluate_formula(row, column)
        # 否则直接返回单元格的值
        return self.matrix[row - 1][col_index]

    def sum(self, row: int, column: str, numbers: List[str]) -> int:
        # 将列号转换为索引
        col_index = ord(column) - ord('A')
        # 计算求和公式的结果,并存储到对应单元格
        self.matrix[row - 1][col_index] = sum(self.get_cell_value(num) for num in numbers)
        # 将求和公式存储到字典中
        self.formulas[(row, column)] = numbers
        # 返回求和结果
        return self.matrix[row - 1][col_index]

    def get_cell_value(self, cell: str) -> int:
        # 如果是单元格范围
        if ':' in cell:
            start, end = cell.split(':')
            start_row, start_col = int(start[1:]), start[0]
            end_row, end_col = int(end[1:]), end[0]
            total = 0
            # 遍历单元格范围,计算所有单元格的值的和
            for r in range(start_row - 1, end_row):
                for c in range(ord(start_col) - ord('A'), ord(end_col) - ord('A') + 1):
                    total += self.get(r + 1, chr(c + ord('A')))
            return total
        # 如果是单个单元格
        else:
            row, col = int(cell[1:]), cell[0]
            # 获取单元格的值
            return self.get(row, col)

    def evaluate_formula(self, row: int, column: str) -> int:
        # 获取单元格的求和公式
        formula = self.formulas[(row, column)]
        # 计算求和公式的结果
        return sum(self.get_cell_value(num) for num in formula)
```

Explore

是的,在`Excel`类的`sum`方法中,如果`numbers`参数包含重复的单元格,这些单元格的值会被重复计算。这种设计可能是合理的,因为在某些情况下,用户可能故意希望某个单元格的值在求和时被计算多次。然而,这也可能导致不必要的计算和性能负担,特别是在处理大量数据时。因此,这种设计的合理性取决于具体应用场景和用户的需求。

根据当前的实现,`set`方法在删除单元格的求和公式后并没有递归地更新依赖于该单元格的其他公式的值。这可能会导致依赖于该单元格的其他单元格的值变得不准确。理想情况下,应该实现一种机制来追踪和更新所有依赖于被修改单元格的公式,以确保数据的一致性和准确性。

在当前的实现中,`get_cell_value`方法在处理单元格范围时没有考虑起始和结束列字符顺序相反的情况。为了正确处理这种情况,应该在计算范围时添加逻辑来确定起始和结束列的正确顺序。如果起始列大于结束列,应该交换它们的位置,确保列的遍历顺序是从小到大。同样的逻辑也应用于行。

在`sum`方法中,每次调用时都会更新`formulas`字典中对应单元格的公式。这意味着,如果一个单元格的求和公式被多次修改,`formulas`字典会直接用新的公式覆盖旧的公式。这样的设计简化了管理公式的复杂度,但也意味着旧的公式信息会被丢失。