LeetCode 168简单数学
Excel 表列名称 图解题解
这道题到底在问什么
给一个正整数 columnNumber,返回它在 Excel 表里对应的列名称。比如 1→A、26→Z、27→AA。
- 输入
- 28
- 输出
- "AB"
- 再如
- 701 → "ZY" · 1 → "A"
最优解:一步一步想明白
- 326 个字母 A~Z 对应 1~26,没有一个字母代表 0。这就是它和真正 26 进制的唯一区别,也是全题的命门。
- 4记住这套口诀:先减 1 → 余 26 取字母 → 除 26 进下一位。下面用 28 一步步演示,盯住 n 怎么变、字母怎么填。
- 5准备从最低位往左填这两个格子是结果的位子,下划线 _ 表示还没填。算法每轮取出一个字母,先取的是低位,所以从最右边那格开始往左放。
- 6指针落在右格,n = 28指针落在最右格,开始第 1 轮。第一步是关键的 n = n − 1:28 变成 27。为什么减?因为 A 代表 1 不是 0,减 1 才能用普通余数取字母。
- 727 % 26 = 1 → B27 % 26 = 1,余数 1 对应字母表第 1 个偏移,也就是 B(A+1)。把 B 填进最右格(变绿)。
- 827 / 26 = 1,右格定稿这一位处理完,n = 27 / 26 = 1(整除)。右格 B 封存。n 还大于 0,说明上面还有一位没取,指针往左挪一格。
- 9指针在左格,n = 1指针到了左格,开始第 2 轮。还是老规矩先减 1:1 − 1 = 0。注意这一减把 1 变 0,正好对上字母表的第 0 个。
- 100 % 26 = 0 → A0 % 26 = 0,余数 0 对应字母表第 0 个,就是 A。填进左格。要不是前面减了 1,这里永远到不了 0,也就出不来 A。
- 110 / 26 = 0,结束n = 0 / 26 = 0,n 归零,循环停。两格从左到右读出来正是 AB——和题目要求一致!
- 12这就是为什么代码里要么把字母塞到字符串最前面,要么先收集再整体反转。本质和「数字转字符串要反转」一模一样。
- 13目标 ZY · 重点看 26 整除换 701 再走一遍,目标 ZY。这次专挑「会不会出现 26 整除」的情况看——那正是减 1 救命的地方。两格先全空。
- 14指针在右格,n = 701指针落最右格。先减 1:701 变 700。下面取这一位的字母。
- 15700 % 26 = 24 → Y700 % 26 = 24,A 往后数 24 个就是 Y。填进最右格。
- 16700 / 26 = 26,封存右格右格 Y 封存,n = 700 / 26 = 26——n 居然又变回 26。要是没减 1,26 直接 %26 会得 0、对不上字母。下一步看减 1 怎么救场。
- 17n: 26 → 25关键!减 1 把 26 变成 25。正是这一减,26 这种「正好整除」的数才不会丢字母。指针已在左格。
- 1825 % 26 = 25 → Z25 % 26 = 25,对应最后一个字母 Z。填进左格。
- 1925 / 26 = 0,结束25 / 26 = 0,n 归零,结束。读出 ZY,完全正确。减 1 这一手,把 26 整除的暗坑稳稳填平了。
- 20指针落右格,n = 1再看最小的 1:只有一格。先减 1 得 0,下面取这唯一一位。
- 210%26=0 → A,0/26=0 结束0 取余得字母 A 填入,除 26 后 n 归零,结果就是单字母 A——边界也对。
- 22两格全空,n = 27最后看刚进两位的 27(目标 AA):指针落右格,n=27。重点体会「26 整除」时怎么借进位多挤出一个字母。
- 2327−1=26,26%26=0 → A再看刚进两位的 27:减 1 得 26,26%26=0 取出 A 填右格,除 26 后 n 还剩 1。下一步指针左移。
- 241−1=0 → A,结果 AA第 2 轮:剩下的 1 减 1 归 0,再取一个 A 填左格,n 归零结束。两格读出 AA——27 进位到两字母,完全正确。
- 2826 % 26 = 0 → 错字母 ✗拿 26 试:正确答案是单字母 Z。但若忘了减 1,26%26=0 错取成 A、再多绕一轮取出 B,倒序拼成 BA——彻底错了。这就是减 1 必须有的铁证。
⚠️ 容易写错的地方
✗ 错:直接 n % 26 取字母
✓ 对:必须先 n = n − 1 再取余
没有 0 这个字母,不减 1 时 26 会取余得 0、对不上字母,Z/AA 全错
✗ 错:取完字母顺着拼
✓ 对:低位先取要倒序(reverse 或往前插)
字母是从最低位开始抠出来的,正着拼会得到反的串
完整代码(Python / C++ / Java)
Python
class Solution:
def convertToTitle(self, columnNumber):
res = []
n = columnNumber
while n > 0:
n -= 1 # 关键:先减 1
res.append(chr(n % 26 + ord('A'))) # 取字母
n //= 26 # 去掉这一位
return ''.join(reversed(res)) # 低位先取,倒序C++
class Solution {
public:
string convertToTitle(int columnNumber) {
string res;
long n = columnNumber;
while (n > 0) {
n -= 1; // 先减 1
res += (char)('A' + n % 26); // 取字母
n /= 26; // 去掉这一位
}
reverse(res.begin(), res.end()); // 倒序
return res;
}
};Java
class Solution {
public String convertToTitle(int columnNumber) {
StringBuilder res = new StringBuilder();
int n = columnNumber;
while (n > 0) {
n -= 1; // 先减 1
res.append((char) ('A' + n % 26)); // 取字母
n /= 26; // 去掉这一位
}
return res.reverse().toString(); // 倒序
}
}复杂度
时间复杂度
O(log₍₂₆₎ n)
每轮 n 都除以 26、规模缩到 1/26,循环次数 = 字母个数,约 log 以 26 为底的 n
空间复杂度
O(log₍₂₆₎ n)
结果串长度 = 字母个数,与循环次数同阶;不算返回串则为 O(1)
看不够?换成动画再走一遍
上面的推演每一步都对应一帧动画。点开交互动画版,能一步步看着 Excel 表列名称 的数据怎么变、指针怎么走,还能切 Python / Java / C++ 跟着练。
面试官可能追问
这题和普通 26 进制差在哪?+
普通进制每位 0~25 有 0;Excel 列每位 1~26 没有 0(称作 bijective base-26)。所以每轮取位前要先减 1 做平移。
为什么结果要倒序?+
字母是从最低位往高位一个个抠出来的,而书写要求高位在左,所以收集顺序和书写顺序相反,需反转或往前插。
反过来 LC171 列名转数字怎么做?+
从左到右遍历每个字母,result = result*26 + (字母−'A'+1),正好是本题的逆运算。
想听吴师兄把这道题讲给你听?
文字版和动画都随便看。开通图解算法年卡,可以听吴师兄声线把 Excel 表列名称 一步步讲透(全站 0 节语音精讲,持续扩充), 卡住的地方还有 AI 私教小欧就着动画帮你拆到懂。
本平台为独立第三方培训机构,与华为技术有限公司无任何关联;课程的服务内容与权益以购买协议为准,学习效果因个人情况而异。「华为 OD」「华为可信」等仅为对岗位与考试方向的客观描述,相关商标归各自权利人所有。