【LeetCode 每日一题】3484. 设计电子表格——(解法一)二维数组
Problem: 3484. 设计电子表格
文章目录
- 整体思路
- 完整代码
- 时空复杂度
- 时间复杂度
- 空间复杂度
整体思路
这个 Spreadsheet
类的设计目标是模拟一个基础的电子表格,支持以下操作:
- 初始化:创建一个具有固定列数(26列,代表’A’到’Z’)和指定行数的表格。
setCell
: 在指定的单元格(如 “A1”, “C10”)中设置一个整数值。resetCell
: 将指定的单元格重置为默认值(推测为0)。getValue
: 解析一个简单的、只包含两个操作数相加的公式(如 “=A1+B2” 或 “=C3+10”),并计算其结果。
为了实现这些功能,该类采用了一个二维数组作为核心数据结构来存储表格数据,并通过一系列方法来解析单元格引用和公式。
-
数据结构:
private final int[][] ans
: 一个26 x (rows+1)
的二维整型数组。- 第一维
26
代表列,从 ‘A’ 到 ‘Z’。 - 第二维
rows+1
代表行,索引从1
到rows
,方便直接使用行号作为索引。 - 这个数组直接存储了每个单元格的数值。
- 第一维
-
setCell(String cell, int value)
操作:- 解析单元格引用:接收一个字符串
cell
(如 “A1”),并将其解析为行列索引。int col = cell.charAt(0) - 'A';
:将列字符 ‘A’, ‘B’, … 转换为数组索引0, 1, ...
。int row = Integer.parseInt(cell.substring(1));
:将字符串的数字部分转换为行索引。
- 赋值:将解析出的
(col, row)
位置的数组元素设置为value
。
- 解析单元格引用:接收一个字符串
-
resetCell(String cell)
操作:- 【逻辑错误】:代码意图是将指定单元格的值重置为0。它调用了
setCell(0)
,但这会产生编译错误,因为setCell
方法需要两个参数(String, int)
。正确的实现应该是调用setCell(cell, 0)
。
- 【逻辑错误】:代码意图是将指定单元格的值重置为0。它调用了
-
getValue(String formula)
操作:- 解析公式:
formula.substring(1)
:去除公式开头的=
。formula1.split("\\+")
:按+
号将公式分割成两个操作数字符串。
- 计算:分别调用
get
方法获取两个操作数的值,然后将它们相加并返回。
- 解析公式:
-
get(String cell)
辅助方法:- 这个方法是一个多功能的值获取器,它可以处理两种类型的输入:
a. 单元格引用(如 “A1”):- 通过检查第一个字符是否是大写字母来判断。
- 如果是一个单元格引用,就解析出
col
和row
,然后从ans
数组中返回对应的值。
b. 立即数(如 “10”): - 如果第一个字符不是大写字母,就假定整个字符串是一个数字。
- 使用
Integer.parseInt(cell)
将其转换为整数并返回。
- 这个方法是一个多功能的值获取器,它可以处理两种类型的输入:
完整代码
class Spreadsheet {// 核心数据结构:二维数组存储单元格的值// 第一维是列 (A-Z -> 0-25),第二维是行 (1-based)private final int[][] ans;/*** 构造函数,初始化一个具有 26 列和指定行数的电子表格。* @param rows 表格的总行数*/public Spreadsheet(int rows) {// 列数固定为 26,行数是 rows+1 以支持 1-based 索引ans = new int[26][rows + 1];}/*** 在指定单元格设置一个整数值。* @param cell 单元格引用字符串,例如 "A1", "C10"* @param value 要设置的整数值*/public void setCell(String cell, int value) {// 解析列:'A' -> 0, 'B' -> 1, ...int col = cell.charAt(0) - 'A';// 解析行:提取数字部分并转换为整数int row = Integer.parseInt(cell.substring(1));// 在二维数组中存储值ans[col][row] = value;}/*** 将指定单元格的值重置为 0。* @param cell 单元格引用字符串*/public void resetCell(String cell) {setCell(cell, 0);}/*** 计算一个简单加法公式的值。* @param formula 公式字符串,例如 "=A1+B2"* @return 公式计算的结果*/public int getValue(String formula) {// 移除开头的 '='String formula1 = formula.substring(1);// 按 '+' 分割成两个操作数String[] values = formula1.split("\\+");// 分别获取两个操作数的值并相加return get(values[0]) + get(values[1]);}/*** 辅助方法:获取一个操作数的值,该操作数可以是单元格引用或立即数。* @param cell 操作数字符串,例如 "A1" 或 "10"* @return 对应的整数值*/public int get(String cell) {char c = cell.charAt(0);// 判断是否是单元格引用 (以大写字母开头)if ('A' <= c && c <= 'Z') {int col = c - 'A';int row = Integer.parseInt(cell.substring(1));// 从二维数组中返回值return ans[col][row];}// 如果不是单元格引用,则解析为立即数return Integer.parseInt(cell);}
}
时空复杂度
- 设
R
为构造时指定的rows
。 - 设
L
为单元格/公式字符串的最大长度。
时间复杂度
-
构造函数
Spreadsheet(int rows)
:- 创建一个
26 * (R+1)
的二维数组。 - 时间复杂度为 O(R)。
- 创建一个
-
setCell(String cell, int value)
:charAt
,substring
,parseInt
等字符串操作的复杂度与字符串长度L
相关。- 时间复杂度为 O(L)。
-
resetCell(String cell)
:- 内部调用
setCell
,所以时间复杂度也是 O(L)。
- 内部调用
-
getValue(String formula)
:substring
,split
的时间复杂度与公式长度L
相关。- 内部调用
get
两次。 - 时间复杂度为 O(L)。
-
get(String cell)
:charAt
,substring
,parseInt
的时间复杂度与字符串长度L
相关。- 时间复杂度为 O(L)。
总结:所有操作的时间复杂度都与输入的字符串长度 L
成正比。对于一个固定的电子表格,如果字符串长度有上界,可以认为是 O(1)。但严格来说,它是 O(L)。
空间复杂度
- 主要存储开销:
private final int[][] ans
: 这是类最主要的内存占用。它的大小是26 * (R + 1)
。
综合分析:
类的空间复杂度由二维数组 ans
决定,为 O®,其中 R
是表格的行数。