题目描述(简单难度)

168. Excel Sheet Column Title - 图1

把数字根据对应规则转为字母。

解法一

这道题的话本质上其实就是进制转换,把 10 进制转为 26 进制表示,可以看一下 这篇文章 对进制转换有个更深的了解。

先讨论一下我们熟悉的 10 进制和 16 进制的转换。

16 进制中,09 还是正常的数字,然后增加字母 A 表示 10,字母 B 表示 11… 以此类推,直到 F 表示 15,所以我们各个位的取值范围是 0 - 15

假如 16 的进制的 A1F 转换为 10 进制的话就用下边的式子,其中 A 表示 10F 表示 15

168. Excel Sheet Column Title - 图2

那么假如我们知道的是 10 进制的 2591,怎么转为 16 进制呢?

我们把上边的等式一般化,设我们要求的每一位分别是 x1,x2,x3...,事先我们并不知道有多少位。

168. Excel Sheet Column Title - 图3

我们可以在等式两边同时模上 16,等式就变成

168. Excel Sheet Column Title - 图4

这样我们就求出来了 x1,接下来我们在等式两边同时除以 16。等式左边由于 x1 的范围是 0 - 15,所以在整数间运算不管 x1 是多少,x1/16 都等于 0,所以等式就变成了下边的样子

168. Excel Sheet Column Title - 图5

和之前对比, 16 的幂都小了 1,同时 x1 消失了。

接下来就可以重复上边的两个步骤,模 16 和除以 16,就可以依次求出 x2x3 …了。

直到除以 16 后变成 0 ,就可以结束了。

对于 10 进制转 26 进制的话是一样的道理,只不过每次采用模 26 和除以 26

所以代码的话,可以直接写出来。

  1. public String convertToTitle(int n) {
  2. StringBuilder sb = new StringBuilder();
  3. while (n > 0) {
  4. int c = n % 26;
  5. sb.insert(0, (char) ('A' + c - 1));
  6. n /= 26;
  7. }
  8. return sb.toString();
  9. }

上边 (char) ('A' + c - 1) 这里的话,算是一个技巧,我们是通过对 A 的偏移,强制将整数转为了字符。

比如 c = 3,那么 'A' + c - 1,会把 A 根据 ASCII 码值转为 65,然后计算 65 + c - 1 = 65 + 3 - 1 = 67,然后 (char)67,根据 ASCII 码值就刚好是字符 C

但是上边的算法还是有问题的,因为题目中每个位的范围是 1-26,而不是0-25

所以取余的话对于 1-25 的数字结果都是正确的,但如果当前的位是 26,余数求出来就是 0,此时我们需要把它修正为 26

此外,我们每次除以 26 是为了把最低位去掉,回忆下之前的等式

168. Excel Sheet Column Title - 图6

因为 x1 的范围正常情况下是 0-25 ,所以除以 26 可以把 x1 去掉,但这道题的范围是 1-26,当 x126 的时候,除以 26 后等式会变成下边的样子

168. Excel Sheet Column Title - 图7

所以当我们再模 26 去求 x2 的话就会发生错误。

修改的话,当我们发现当前位是 26 的时候,我们应该在等式两边减去一个 1

168. Excel Sheet Column Title - 图8

这样两边再同时除以 26 的时候,就可以把 x1 去掉了。

代码修正后如下。

  1. public String convertToTitle(int n) {
  2. StringBuilder sb = new StringBuilder();
  3. while (n > 0) {
  4. int c = n % 26;
  5. if(c == 0){
  6. c = 26;
  7. n -= 1;
  8. }
  9. sb.insert(0, (char) ('A' + c - 1));
  10. n /= 26;
  11. }
  12. return sb.toString();
  13. }

这道题看做是进制转换问题的变形,只要知道进制转换的原理,改这道题的话也不难。

区别就在于题目规定的数字中没有 0 ,换句话讲,正常的 26 进制本应该满 261,然后低位补 0,但是这里满 26 的话就用 26 表示。满 27 的时候才会向前进 1,然后低位补 1。所以 Z(26) 的下一个数字就是 A(1)A(1),即 27 对应 AA

windliang wechat

添加好友一起进步~

如果觉得有帮助的话,可以点击 这里 给一个 star 哦 ^^

如果想系统的学习数据结构和算法,强烈推荐一个我之前学过的课程,可以点击 这里 查看详情