LeetCode168、Excel表列名称

129 阅读2分钟

LeetCode 系列记录我学习算法的过程。

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第26天,点击查看活动详情

题目

给你一个整数 columnNumber ,返回它在 Excel 表中相对应的列名称。

例如:

A -> 1
B -> 2
C -> 3
...
Z -> 26
AA -> 27
AB -> 28 
...

示例:

输入: columnNumber = 1
输出: "A"

输入: columnNumber = 28
输出: "AB"

输入: columnNumber = 701
输出: "ZY"


输入: columnNumber = 2147483647
输出: "FXSHRXW"

提示:

  • 1 <= columnNumber <= 231 - 1

思路

这个题目刚一开始看确实感觉很容易,就是一个变相的 27 进制嘛,满 27 进位

自信十足的写完代码提交才发现一直通过不了,然后仔细琢磨了一下才发现并不简单

正常进位是进一位后补 0, 但是它这里没有 0, 进位后直接补 1, 这就比较坑了

也是琢磨了很久才想到解决方法,就是将它看成 26 进制,将 Z 当成 10 来实现进位:

  • 首先定义变量存储所有字符,首位为空字符
  • 然后进行循环操作,直到数值为 0
  • 首先获取进位数及当前余数
  • 根据当前余数获取对应的字符下标
  • 将对应的字符与记录的结果拼接起来,下标为 0 时要设置为最后一位 26
  • 最后将结果返回即可

代码实现

/**
 * @param {number} columnNumber
 * @return {string}
 */

var convertToTitle = function(columnNumber) {
    // 首先定义变量存储所有的字符
    let char = ['', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z']
    // 定义变量 str 存储结果,num进行循环
    let str = '', num = columnNumber

    do {
        // 获取进位
        const quotient = Math.floor(num / 26)
        // 获取余数
        const remainder = num % 26

        // 获取余数对于的字符下标
        num = remainder === 0 ? quotient - 1 : quotient
        // 下标为0时设置为最后一位 26
        str = char[remainder === 0 ? 26 : remainder] + str
    } while (num)

    // 最后返回结果
    return str
};

image.png

优化

其实这个题目和正常的 0~2526 进制相比,本质上就是每一位多加了 1。假设 A == 0B == 1,那么 AB = 26 * 0 + 1 * 1,而现在 AB = 26 * (0 + 1) + 1 * (1 + 1),所以只要在处理每一位的时候减 1,就可以按照正常的 26 进制来处理

这里将代码简化一下写法:

var convertToTitle = function(columnNumber) {
    const res = []
    while (columnNumber !== 0) {
        columnNumber--
        res.unshift(String.fromCharCode(columnNumber % 26 + 'A'.charCodeAt()))
        columnNumber = Math.floor(columnNumber / 26)
    }
    return res.join('')
};

image.png