来源
力扣(LeetCode)
题目内容
给定一个正整数,返回它在 Excel 表中相对应的列名称。
例如,
1 -> A
2 -> B
3 -> C
...
26 -> Z
27 -> AA
28 -> AB
...
示例 1:
输入: 1
输出: A
示例 2:
输入: 28
输出: AB
示例 3:
输入: 701
输出: ZY
思路
这一题,本来以为使用进制转换可以快速做出来。然而在做的时候发现还是太天真了。
因此带来的经验教训是,不要眼高手低
这个字母26进制与一般的进制是不同的。
以下是推导过程:
对于进制转换,我们有:
设
a
i
a_i
ai 为从右往左每一位上的数字,则:
n
u
m
b
e
r
=
∑
i
=
0
n
−
1
a
i
∗
2
6
i
number = \sum_{i=0}^{n-1}a_i * 26^{i}
number=i=0∑n−1ai∗26i
我们把
a
0
a_0
a0 先提出来:
n
u
m
b
e
r
=
a
0
+
∑
i
=
1
n
−
1
a
i
∗
2
6
i
number = a_0 + \sum_{i=1}^{n-1}a_i * 26^{i}
number=a0+i=1∑n−1ai∗26i
再变形得:
n
u
m
b
e
r
=
a
0
+
26
∗
∑
i
=
1
n
−
1
a
i
∗
2
6
i
−
1
number = a_0 +26 * \sum_{i=1}^{n-1}a_i * 26^{i-1}
number=a0+26∗i=1∑n−1ai∗26i−1
两边同时减1
:
n
u
m
b
e
r
−
1
=
(
a
0
−
1
)
+
26
∗
∑
i
=
1
n
−
1
a
i
∗
2
6
i
−
1
number -1 = (a_0 - 1) +26 * \sum_{i=1}^{n-1}a_i * 26^{i-1}
number−1=(a0−1)+26∗i=1∑n−1ai∗26i−1
由上面的式子我们可以很容易看到:
a 0 − 1 a_0 - 1 a0−1 是 n u m b e r − 1 number - 1 number−1 除以 26 26 26 的余数。
这样 a 0 − 1 a_0 - 1 a0−1 的值我们就求出来了
接下来是更新后的number
值
不妨把更新后的number
值设为number'
那么:
n
u
m
b
e
r
′
=
(
(
n
u
m
b
e
r
−
1
)
−
(
a
0
−
1
)
)
/
26
=
∑
i
=
1
n
−
1
a
i
∗
2
6
i
−
1
number' = ((number - 1) - (a_0 - 1)) / 26 = \sum_{i=1}^{n-1}a_i * 26^{i-1}
number′=((number−1)−(a0−1))/26=i=1∑n−1ai∗26i−1
这样就回到了最初的
n
u
m
b
e
r
=
∑
i
=
0
n
−
1
a
i
∗
2
6
i
number = \sum_{i=0}^{n-1}a_i * 26^{i}
number=∑i=0n−1ai∗26i 了
因此代码的思路就很快能够写出来。
代码
class Solution {
public:
unordered_map<int,char> chara={
{1,'A'},
{2,'B'},
{3,'C'},
{4,'D'},
{5,'E'},
{6,'F'},
{7,'G'},
{8,'H'},
{9,'I'},
{10,'J'},
{11,'K'},
{12,'L'},
{13,'M'},
{14,'N'},
{15,'O'},
{16,'P'},
{17,'Q'},
{18,'R'},
{19,'S'},
{20,'T'},
{21,'U'},
{22,'V'},
{23,'W'},
{24,'X'},
{25,'Y'},
{26,'Z'},
};
string convertToTitle(int columnNumber) {
string ans;
int a;
while(columnNumber!=0){
a = (columnNumber-1) % 26 + 1;
columnNumber = (columnNumber -a) / 26;
ans = ans + chara[a];
}
reverse(ans.begin(),ans.end());
return ans;
}
};