生成 Excel 表列名称

Excel 大家都用过,它的列名是用字母编号的,A 表示第一列,B 表示第二列,AA 表示第27列,AB 表示第28列等等。

现给定一个数字,如何得到列名称呢。比如输入28,输出 AB。

一开始以为就是一个简单的26进制转换,到底还是大意了,这里的每一位都是没有0的,而且能取到进制的最大值。正常26进制每一位都是0到25,但是这里却是1到26。

算法原理还是不停的取模和取余来得到每一位的值。只不过和正常的 n 进制转换不同,我们不能直接用 n 去取模和取余,而是应该用 n-1。

还是按26进制计算,假设要表示的数为 num,余数为 r,则:
n u m = n × 26 + r num = n \times 26+r num=n×26+r

其中 r r r 的范围是0到25,假设 R R R 的范围是1到26,我们将 r r r 线性映射到 R R R,并将 r r r 替换成 R R R,于是:
n × 26 + R = n u m + 1 n \times 26+R=num+1 n×26+R=num+1

我们会发现在将 r r r 替换成 R R R 的过程中, n u m num num 实际上每次都多加了1,所以在计算每一位的值时要将它减出来。

另外我们可以想一下,在取余的过程中,有两种情况:
n u m = n × 26 + r n u m = n × 26 \begin{align} num & = n \times 26 + r \\ num & = n \times 26 \end{align} numnum=n×26+r=n×26

第一种情况其实可以正常计算,第二中情况不行,因为不会出现0,所以我们需要改写一下:
n u m = ( n − 1 ) × 26 + 26 num=(n-1)\times 26 + 26 num=(n−1)×26+26

但是正常取余运算算不出这个余数,怎么办呢,给 n u m num num 减去1就可以了:
n u m − 1 = ( n − 1 ) × 26 + 25 num-1=(n-1)\times 26 + 25 num−1=(n−1)×26+25

对于其他情况也一样,于是就统一变成了:
n u m − 1 = n × 26 + ( r − 1 ) num-1=n \times 26 + (r-1) num−1=n×26+(r−1)

至于多减的1,会自动补回来。

elixir 复制代码
defmodule Solution do
  @spec convert_to_title(column_number :: integer) :: String.t
  def convert_to_title(column_number) do
    {column_number, 26}
    |> Stream.unfold(fn
            {0, _} -> nil
            {n, m} -> {rem(n - 1, m) + ?A, {div(n - 1, m), m}}  
        end)
    |> Enum.reverse
    |> List.to_string
  end
end

在 Elixir 中,我们可以通过 Stream.unfold 来构造每一位的值,连递归都不用写了,可以说是十分优雅了。


相关推荐
We་ct1 小时前
LeetCode 5. 最长回文子串:DP + 中心扩展
前端·javascript·算法·leetcode·typescript
王老师青少年编程5 小时前
csp信奥赛C++高频考点专项训练之贪心算法 --【哈夫曼贪心】:合并果子
c++·算法·贪心·csp·信奥赛·哈夫曼贪心·合并果子
叼烟扛炮6 小时前
C++第二讲:类和对象(上)
数据结构·c++·算法·类和对象·struct·实例化
天疆说6 小时前
【哈密顿力学】深入解读航天器交会最优控制中的Hamilton函数
人工智能·算法·机器学习
wuweijianlove7 小时前
关于算法设计中的代价函数优化与约束求解的技术7
算法
leoufung7 小时前
LeetCode 149: Max Points on a Line - 解题思路详解
算法·leetcode·职场和发展
样例过了就是过了7 小时前
LeetCode热题100 最长公共子序列
c++·算法·leetcode·动态规划
HXDGCL8 小时前
矩形环形导轨:自动化循环线的核心运动单元解析
运维·算法·自动化
谭欣辰8 小时前
C++ 排列组合完整指南
开发语言·c++·算法
代码中介商8 小时前
银行管理系统的业务血肉 —— 流程、状态机、输入校验与持久化(下篇)
c语言·算法