LeetCode 168 – Excel Sheet Column Title

January 23, 20254 min readUpdated 8/25/2026

Excel Sheet Column Title looks like a base-26 conversion and is not quite. Excel's columns have no zero — the digits run A to Z with no symbol for "nothing" — and that single missing digit is the entire problem. The fix is one line, and knowing why it is needed is what separates a working solution from a lucky one.

The problem

Given a positive integer, return its Excel column title.

1   -> "A"
26  -> "Z"
27  -> "AA"
28  -> "AB"
52  -> "AZ"
53  -> "BA"
701 -> "ZY"
702 -> "ZZ"
703 -> "AAA"

26 → "Z" and 27 → "AA" are the two to check any solution against. They are exactly where ordinary base-26 goes wrong.

Why plain base-26 fails

Normal base-26 has digits 0–25. Excel has 26 digits, A–Z, and they represent 1–26. There is no zero:

base 26:   0, 1, 2, ..., 25, then 10  (meaning 26)
Excel:     A, B, C, ..., Z,  then AA  (meaning 27)

26 % 26 = 0   -> there is no digit for 0, and Z is what we want

This is called a bijective numeral system: every positive integer has exactly one representation and no representation has a leading-zero ambiguity, because zero does not exist. Naming it is worth a sentence — it tells the interviewer you have identified the actual structure rather than patched until the tests passed.

The one-line fix

while (n > 0) {
    n--;                          <- shift THIS digit into 0..25
    digit = 'A' + n % 26;
    n /= 26;
}

Decrementing before taking the remainder converts the 1–26 digit into a 0–25 one, so the arithmetic becomes ordinary base-26 for that step. The decrement must happen inside the loop, once per digit — doing it once before the loop fixes 26 and breaks 27.

n = 28:  n-- -> 27,  27 % 26 = 1  -> 'B',  27 / 26 = 1
         n-- -> 0,    0 % 26 = 0  -> 'A',   0 / 26 = 0
         reversed: "AB"

n = 26:  n-- -> 25,  25 % 26 = 25 -> 'Z',  25 / 26 = 0
         reversed: "Z"

Java

class Solution {
    public String convertToTitle(int columnNumber) {
        StringBuilder title = new StringBuilder();

        while (columnNumber > 0) {
            // Excel's digits are 1..26 with no zero, so shift this one to 0..25.
            columnNumber--;

            title.append((char) ('A' + columnNumber % 26));
            columnNumber /= 26;
        }

        return title.reverse().toString();
    }
}

Digits come out least-significant first, so the result is reversed once at the end — O(n) in the length of the title. Inserting at index 0 each iteration would be O(n²), the same trap as Add Binary and postorder traversal.

No overflow concern: the loop only divides. The inverse problem (Excel Sheet Column Number, 171) multiplies and does need the check.

Python

class Solution:
    def convertToTitle(self, columnNumber: int) -> str:
        title = []

        while columnNumber > 0:
            columnNumber -= 1                          # 1..26 becomes 0..25
            title.append(chr(ord("A") + columnNumber % 26))
            columnNumber //= 26

        return "".join(reversed(title))

// and not /. Python's / produces a float, and columnNumber would silently become 26.0, then 1.0, and chr would raise on a float argument — a crash rather than a wrong answer, but a crash that only appears past 26.

Build a list and join, rather than concatenating strings in a loop. Same reasoning as the Java reversal.

Complexity

TimeSpace
Digit extractionO(log₂₆ n)O(log₂₆ n) output

One iteration per output character, and the title has about log₂₆ n of them — Integer.MAX_VALUE is "FXSHRXW", seven characters. Effectively constant, but say the logarithm rather than "constant"; the interviewer is checking that you know what the loop is bounded by.

The inverse, and the sanity check

Excel Sheet Column Number (171) goes the other way and is the easier direction, precisely because no shift is needed:

result = 0
for each character c:
    result = result * 26 + (c - 'A' + 1)     the +1 IS the bijective part

The two are inverses, which makes an excellent self-check: convert every number in a range to a title and back, and confirm you get the original. That round-trip catches every off-by-one the shift can produce, and it is the sort of test worth proposing out loud even when you cannot run it.

Where else bijective numbering shows up

Anywhere labels start at 1 rather than 0 and then carry: spreadsheet columns, some invoice numbering schemes, and bijective base-k in combinatorics. The give-away is a system where k symbols represent 1..k rather than 0..k−1, and the fix is always the same decrement.

What the interviewer is checking

  • That you notice there is no zero digit, and can name why that matters.
  • The decrement inside the loop, once per digit — not once before it.
  • 26 → "Z" and 27 → "AA", the two boundary cases.
  • Reversing once rather than prepending in a loop.
  • Integer division in Python.
  • That you can state the inverse and propose the round-trip check.