题目描述

✅ 171. Excel 表列序号

image-20260928220241515

image-20260928220241516

题意分析

将 Excel 列名转为列序号,每个字母 A..Z 对应数值 1..26,越靠左的字母权重越大。这套编号没有表示 0 的字母,因此当前位的值是 字母-'A'+1。

解法:按 26 进制累加

核心思路

[!blue]

列名的相邻两位权重相差 26 倍。若已经处理的前缀对应序号 ans,在右侧追加一个字母后,原来每一位都向高位移动一位,所以整个旧前缀的贡献变成 ans*26;新字母处在最低位,再加上它的值 value 即可。

因此从左到右反复执行 ans = ans*26 + value。初始 ans = 0 表示空前缀,每次更新后都得到当前前缀的序号,读完全部字母便是答案,不需要反转字符串或计算幂。

这里与普通进制转换的区别只在数位取值:字母对应 1..26,不能映射成 0..25,也不需要使用反向转换列名时的减一操作。

解题步骤

  • 初始化 ans = 0,表示尚未读入字符的空前缀。
  • 从左到右遍历列名,将当前字符映射为 1 到 26。
  • 执行 ans = ans * 26 + value,使 ans 等于当前已读前缀的序号。
  • 遍历结束后返回 ans。

代码实现

class Solution {
    public int titleToNumber(String columnTitle) {
        int ans = 0;

        for (int idx = 0; idx < columnTitle.length(); idx++) {
            int value = columnTitle.charAt(idx) - 'A' + 1;

            // 旧前缀提升一位,再加入从一开始编号的当前字母。
            ans = ans * 26 + value;
        }

        return ans;
    }
}
func titleToNumber(columnTitle string) int {
    ans := 0
    for idx := 0; idx < len(columnTitle); idx++ {
        value := int(columnTitle[idx]-'A') + 1
        // 旧前缀提升一位,再加入从一开始编号的当前字母。
        ans = ans*26 + value
    }
    return ans
}

复杂度分析

  • 时间复杂度:$O(n)$,n 为列名长度,每个字符只处理一次。
  • 空间复杂度:$O(1)$,只维护累加结果和当前字符值。

关键点总结

[!green]

  • A 映射为 1,Z 映射为 26;字母表里没有表示 0 的数位。
  • 从高位到低位使用“旧值乘基数再加新位”,可以省去反转、求幂和额外存储。
  • 题目保证答案不超过 2147483647;累加过程中每次结果都不超过最终答案,使用 int 足够。

易错点总结

[!yellow]

  • 忘记字符映射中的 +1,会把整套从 1 开始的编号错当成从 0 开始。
  • 当前递推要求从左往右读取;乘 26 的对象是已经处理的前缀,不能写成 ans + 26*value。
  • 不要套用反向转换列名时的“先减一”规则,这里直接累加每个字母对应的 1..26。

相似题目

题目 难度 关联与区别
168. Excel 表列名称 简单 反向转换把数值生成列名,本题按26倍累积,每个字母贡献1到26而非0到25。
转载与许可
作者
链接 https://hgnulb.github.io/blog/2022/16028851
许可 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处!