Excel Sheet Column Title
Convert a positive integer to its corresponding Excel column title.
- 1 <= columnNumber <= 2³¹ - 1
Intuition
Excel sheet column title converts a number into its Excel column name — 1 becomes "A", 28 becomes "AB". It is the reverse of the column-number problem and is genuinely harder, for one specific reason.
Excel columns are bijective base-26: letters represent 1 through 26 and there is no digit for zero. Standard base conversion assumes a zero digit exists, so applying it directly produces wrong output whenever a remainder of zero appears:
- Decrement the number by 1 before each division, which shifts the remainder range from 1–26 into the 0–25 that modular arithmetic expects.
Without that decrement, 26 gives a remainder of 0, which maps to no letter at all. With it, 26 − 1 = 25 maps cleanly to Z and the quotient becomes 0, ending the loop correctly.
Each iteration then takes (n − 1) % 26 as the letter and (n − 1) / 26 as the new value. The decrement must happen before both operations, not just the modulo — using the undecremented value for the division leaves an extra column and produces titles one letter too long.
Characters come out least significant first, so the accumulated string must be reversed at the end, or built by prepending.
A quick check: 26 should give "Z", 27 should give "AA", and 52 should give "AZ". Those three cover the boundary where the missing zero digit does its damage.
Base-26 with no zero digit — A is 1, not 0, so the usual conversion is off by one at every place. Decrementing n before each modulo shifts the range from 1–26 down to 0–25, which is what the alphabet indexing expects.
Approach
Before reading on: price up what enumerating every case costs here, then ask what pattern in the numbers removes the loop entirely. Aim for O(log n) time and O(log n) space.
Identify the bijective base
Letters represent 1 through 26 with no zero digit. Standard base conversion assumes a zero exists, which is precisely why it fails here.
Decrement before dividing
Subtract 1 from the number each iteration. This shifts remainders from 1–26 into the 0–25 that modular arithmetic expects, without which 26 yields a remainder of 0 mapping to no letter.
Apply the decrement to both operations
Use (n - 1) % 26 for the letter and (n - 1) / 26 for the next value. Dividing the undecremented number leaves an extra column and produces titles one letter too long.
Map the remainder to a letter
Add the remainder to 'A' to get the character. With the decrement applied, 0 maps to A and 25 to Z, covering the full range.
Reverse the result
Characters are produced least significant first, so reverse the accumulated string at the end, or prepend each character as it is computed.
Verify the boundary cases
Check that 26 gives "Z", 27 gives "AA", and 52 gives "AZ". These three expose every error the missing zero digit causes.
Cost of the conversion
The number shrinks by a factor of 26 each step, giving O(log₂₆ n) time and O(log₂₆ n) space for the output string.
Solution & live demo
Common pitfalls
Not decrementing before the modulo
result.append(chr(65 + n % 26)) n //= 26
n -= 1 result.append(chr(65 + n % 26)) n //= 26
Column 26 is "Z", but 26 % 26 is 0, producing "A" with a stray carry. Subtracting 1 first maps 26 to index 25 and makes the division carry correctly.
Forgetting to reverse the result
return ''.join(result)
return ''.join(reversed(result))
Digits are peeled off from the least significant end, so they accumulate backwards. 701 would print as "AZ" reversed into "ZA" — a valid-looking but wrong column.
Treating it as standard base 26
digits = [] while n: digits.append(n % 26); n //= 26
n -= 1
Standard base-26 has a zero digit, so it can represent "A0"-like values that don't exist in Excel's scheme. This is a bijective numeration system, and the decrement is what encodes that difference.
Edge cases
Subtracting 1 first gives 25, which mods to 25 -> 'Z', then divides to 0, stopping immediately - not 'AZ'.
Subtract 1 to get 26; 26 % 26 = 0 -> 'A', then 26 // 26 = 1, one more round gives 'A' again for the tens place -> 'AA'.
Subtract 1 to get 0; 0 % 26 = 0 -> 'A', divides to 0, loop ends -> 'A'.
Multiple rounds of subtract-mod-divide each contribute one letter, correctly producing multi-character titles like 'ZY'.