168. Excel Sheet Column Title
Problem Description
This problem asks you to convert a positive integer into its corresponding Excel column title representation.
In Excel spreadsheets, columns are labeled using letters from the alphabet. The first 26 columns use single letters (A through Z), where:
- Column 1 is labeled "A"
- Column 2 is labeled "B"
- Column 26 is labeled "Z"
After exhausting single letters, Excel uses two-letter combinations:
- Column 27 is labeled "AA"
- Column 28 is labeled "AB"
- Column 52 is labeled "AZ"
- Column 53 is labeled "BA"
This pattern continues with three letters, four letters, and so on.
The task is to write a function that takes a column number (positive integer) and returns the corresponding Excel column title as a string.
This is essentially a base-26 number system conversion with a twist - instead of digits 0-25, we use letters A-Z (representing 1-26). The key difference from standard base conversion is that there's no zero in this system, making it a bijective base-26 numeral system.
For example:
- Input:
1
→ Output:"A"
- Input:
26
→ Output:"Z"
- Input:
27
→ Output:"AA"
- Input:
701
→ Output:"ZY"
Intuition
The key insight is recognizing this as a base conversion problem, but with a crucial difference from standard base conversions. In typical base-26, we'd have digits 0-25, but Excel columns use A-Z representing 1-26, with no representation for 0.
Think about how standard base conversion works. To convert a decimal number to base-26, we repeatedly divide by 26 and collect remainders. For example, converting decimal 28 to standard base-26 would give us 28 = 1×26 + 2
, so we'd get "12" (where 1 and 2 are the base-26 digits).
But in Excel's system, there's no digit for 0. The letters A-Z represent values 1-26, not 0-25. This creates an interesting situation: when we have a number perfectly divisible by 26, like 26 itself, it should map to 'Z' (the 26th letter), not to 'BA' (which would be 27).
The trick is to adjust our number before each division step. By subtracting 1 from the column number before taking the modulo, we shift the range from 1-26 to 0-25, which aligns perfectly with how we can index letters:
(1-1) % 26 = 0
→ 'A' (0th position from 'A')(26-1) % 26 = 25
→ 'Z' (25th position from 'A')(27-1) % 26 = 0
→ 'A' (for the rightmost digit of "AA")
After getting each digit, we divide by 26 to process the next position. The subtraction of 1 before each operation ensures that numbers like 26, 52, etc., correctly map to 'Z', 'AZ', rather than rolling over prematurely.
We build the result from right to left (least significant to most significant position), then reverse it at the end to get the correct order. This approach elegantly handles the "no zero" nature of Excel's column naming system.
Solution Approach
The implementation follows a straightforward algorithm that processes the column number digit by digit from right to left:
-
Initialize an empty list
res
to store the characters of our result. We use a list instead of string concatenation for better performance since strings are immutable in Python. -
Process digits in a loop while
columnNumber > 0
:- Adjust for 1-based indexing: Subtract 1 from
columnNumber
to convert from 1-26 range to 0-25 range - Extract the current digit: Calculate
columnNumber % 26
to get the remainder (0-25) - Convert to letter: Add this remainder to
ord('A')
to get the ASCII value of the corresponding letter, then convert it to a character usingchr()
- Append to result: Add this character to our result list
- Move to next position: Integer divide
columnNumber
by 26 using//=
operator
- Adjust for 1-based indexing: Subtract 1 from
-
Reverse and join: Since we built the result from least significant to most significant digit, we need to reverse it. We use
res[::-1]
to reverse the list and''.join()
to convert it to a string.
Let's trace through an example with columnNumber = 28
:
- First iteration:
28 - 1 = 27
,27 % 26 = 1
, append 'B' (A + 1),columnNumber = 27 // 26 = 1
- Second iteration:
1 - 1 = 0
,0 % 26 = 0
, append 'A' (A + 0),columnNumber = 0 // 26 = 0
- Result list:
['B', 'A']
- After reversal:
['A', 'B']
- Final output:
"AB"
The time complexity is O(log₂₆ n)
where n is the column number, as we divide by 26 in each iteration. The space complexity is also O(log₂₆ n)
for storing the result characters.
Ready to land your dream job?
Unlock your dream job with a 3-minute evaluator for a personalized learning plan!
Start EvaluatorExample Walkthrough
Let's walk through converting column number 701 to its Excel column title "ZY":
Initial State: columnNumber = 701
, res = []
Iteration 1:
- Adjust for 1-based indexing:
701 - 1 = 700
- Extract current digit:
700 % 26 = 24
- Convert to letter:
chr(ord('A') + 24) = chr(65 + 24) = chr(89) = 'Y'
- Append 'Y' to result:
res = ['Y']
- Move to next position:
columnNumber = 700 // 26 = 26
Iteration 2:
- Adjust for 1-based indexing:
26 - 1 = 25
- Extract current digit:
25 % 26 = 25
- Convert to letter:
chr(ord('A') + 25) = chr(65 + 25) = chr(90) = 'Z'
- Append 'Z' to result:
res = ['Y', 'Z']
- Move to next position:
columnNumber = 25 // 26 = 0
Loop terminates (columnNumber = 0)
Final Steps:
- Reverse the list:
res[::-1] = ['Z', 'Y']
- Join to form string:
''.join(['Z', 'Y']) = "ZY"
Output: "ZY"
The key insight here is how subtracting 1 before each modulo operation correctly handles the mapping. Notice that when we had exactly 26 remaining in iteration 2, subtracting 1 gave us 25, which maps to 'Z' (the 26th letter). Without this adjustment, we would incorrectly get 'AA' instead of 'Z' for column 26.
Solution Implementation
1class Solution:
2 def convertToTitle(self, columnNumber: int) -> str:
3 """
4 Convert a column number to Excel column title.
5
6 Args:
7 columnNumber: A positive integer representing the column number
8
9 Returns:
10 A string representing the corresponding Excel column title
11
12 Example:
13 1 -> "A", 26 -> "Z", 27 -> "AA", 28 -> "AB"
14 """
15 result = []
16
17 # Convert number to base-26 representation with letters A-Z
18 while columnNumber > 0:
19 # Subtract 1 to handle 1-indexed to 0-indexed conversion
20 # (Excel columns start at 1, but we need 0-25 for modulo operation)
21 columnNumber -= 1
22
23 # Get the current digit (0-25) and convert to corresponding letter
24 current_digit = columnNumber % 26
25 current_letter = chr(ord('A') + current_digit)
26 result.append(current_letter)
27
28 # Move to the next position (divide by 26)
29 columnNumber //= 26
30
31 # Reverse the result since we built it from least to most significant digit
32 return ''.join(result[::-1])
33
1class Solution {
2 /**
3 * Converts a column number to Excel column title.
4 * For example: 1 -> A, 2 -> B, ..., 26 -> Z, 27 -> AA, 28 -> AB
5 *
6 * @param columnNumber The column number to convert (1-indexed)
7 * @return The corresponding Excel column title as a string
8 */
9 public String convertToTitle(int columnNumber) {
10 // Use StringBuilder for efficient string concatenation
11 StringBuilder result = new StringBuilder();
12
13 // Continue conversion while there are digits to process
14 while (columnNumber != 0) {
15 // Decrement by 1 to convert from 1-indexed to 0-indexed
16 // This is crucial because Excel columns are 1-indexed (A=1, B=2, etc.)
17 // but we need 0-indexed for modulo operation (A=0, B=1, etc.)
18 columnNumber--;
19
20 // Get the current digit (0-25) and convert to corresponding letter (A-Z)
21 // columnNumber % 26 gives us the rightmost digit in base-26
22 char currentChar = (char) ('A' + columnNumber % 26);
23 result.append(currentChar);
24
25 // Move to the next digit position by dividing by 26
26 columnNumber /= 26;
27 }
28
29 // Reverse the result since we built it from right to left
30 return result.reverse().toString();
31 }
32}
33
1/**
2 * Converts a column number to its corresponding Excel column title
3 * @param columnNumber - The column number to convert (1-indexed)
4 * @returns The Excel column title as a string (e.g., 1 -> "A", 27 -> "AA")
5 */
6string convertToTitle(int columnNumber) {
7 // String to store the result
8 string result = "";
9
10 // Continue until all digits are processed
11 while (columnNumber > 0) {
12 // Adjust to 0-indexed (A=0, B=1, ..., Z=25)
13 columnNumber--;
14
15 // Get the remainder which represents the current character
16 int remainder = columnNumber % 26;
17
18 // Convert number to corresponding letter (0->A, 1->B, ..., 25->Z)
19 // 'A' + remainder gives us the correct character
20 char current_character = 'A' + remainder;
21
22 // Add character to the beginning of the result string
23 result = current_character + result;
24
25 // Move to the next digit position
26 columnNumber = columnNumber / 26;
27 }
28
29 // Return the final string
30 return result;
31}
32
1/**
2 * Converts a column number to its corresponding Excel column title
3 * @param columnNumber - The column number to convert (1-indexed)
4 * @returns The Excel column title as a string (e.g., 1 -> "A", 27 -> "AA")
5 */
6function convertToTitle(columnNumber: number): string {
7 // Array to store characters of the result in reverse order
8 const resultCharacters: string[] = [];
9
10 // Continue until all digits are processed
11 while (columnNumber > 0) {
12 // Adjust to 0-indexed (A=0, B=1, ..., Z=25)
13 columnNumber--;
14
15 // Get the remainder which represents the current character
16 const remainder: number = columnNumber % 26;
17
18 // Convert number to corresponding letter (0->A, 1->B, ..., 25->Z)
19 // 65 is ASCII code for 'A'
20 const currentCharacter: string = String.fromCharCode(remainder + 65);
21
22 // Add character to the beginning of the result array
23 resultCharacters.unshift(currentCharacter);
24
25 // Move to the next digit position
26 columnNumber = Math.floor(columnNumber / 26);
27 }
28
29 // Join all characters to form the final string
30 return resultCharacters.join('');
31}
32
Time and Space Complexity
Time Complexity: O(log₂₆(n))
where n
is the input columnNumber
. The while loop executes approximately log₂₆(n)
times since we're dividing columnNumber
by 26 in each iteration until it becomes 0. Each operation inside the loop (subtraction, modulo, integer division, and character append) takes O(1)
time. The final reverse operation res[::-1]
takes O(k)
time where k
is the length of the result string, which is also O(log₂₆(n))
. Therefore, the overall time complexity is O(log₂₆(n))
.
Space Complexity: O(log₂₆(n))
where n
is the input columnNumber
. The space is used to store the result list res
, which contains approximately log₂₆(n)
characters corresponding to the number of digits in base-26 representation. The reversed string also takes the same amount of space. Since we need to return the string anyway, if we only count auxiliary space, it would still be O(log₂₆(n))
for the intermediate list storage.
Common Pitfalls
Pitfall: Treating it as a Standard Base-26 Conversion
The most common mistake is treating this as a regular base-26 number system (with digits 0-25) instead of recognizing it as a bijective base-26 system (with digits 1-26). This leads to incorrect implementations like:
Incorrect Approach:
def convertToTitle_wrong(columnNumber: int) -> str:
result = []
while columnNumber > 0:
# WRONG: This doesn't handle the 1-indexed nature correctly
result.append(chr(ord('A') + columnNumber % 26))
columnNumber //= 26
return ''.join(result[::-1])
This fails for many cases, particularly multiples of 26:
- Input:
26
produces"A@"
instead of"Z"
(since 26 % 26 = 0, and chr(ord('A') + 0) would try to use '@' which is before 'A') - Input:
52
produces incorrect results instead of"AZ"
Why This Happens
In standard base conversions (like decimal to binary), we have digits 0 through (base-1). However, Excel columns use A-Z representing 1-26, with no representation for 0. This creates a shifted number system where:
- There's no "0" digit
- When we would normally get a remainder of 0, we actually want 'Z' (the 26th letter)
- We need to "borrow" from the next higher position
The Solution
The key insight is to subtract 1 from columnNumber
before each modulo operation. This transforms the problem:
- Instead of working with 1-26, we work with 0-25
- This aligns perfectly with modulo 26 operations (which give 0-25)
- After getting the remainder, we can directly map 0→'A', 1→'B', ..., 25→'Z'
Correct Implementation:
def convertToTitle(columnNumber: int) -> str:
result = []
while columnNumber > 0:
columnNumber -= 1 # Critical: Convert from 1-indexed to 0-indexed
result.append(chr(ord('A') + columnNumber % 26))
columnNumber //= 26
return ''.join(result[::-1])
Verification Examples
Let's verify with edge cases:
columnNumber = 26
: After subtracting 1, we get 25. 25 % 26 = 25, which maps to 'Z'. ✓columnNumber = 27
: First iteration: 27-1=26, 26%26=0 → 'A', 26//26=1. Second iteration: 1-1=0, 0%26=0 → 'A'. Result: "AA" ✓columnNumber = 52
: First iteration: 52-1=51, 51%26=25 → 'Z', 51//26=1. Second iteration: 1-1=0, 0%26=0 → 'A'. Result: "AZ" ✓
The subtraction effectively handles the "carry" operation needed when transitioning from Z to AA, AZ to BA, etc.
Consider the classic dynamic programming of longest increasing subsequence:
Find the length of the longest subsequence of a given sequence such that all elements of the subsequence are sorted in increasing order.
For example, the length of LIS for [50, 3, 10, 7, 40, 80]
is 4
and LIS is
[3, 7, 40, 80]
.
What is the recurrence relation?
Recommended Readings
Math for Technical Interviews How much math do I need to know for technical interviews The short answer is about high school level math Computer science is often associated with math and some universities even place their computer science department under the math faculty However the reality is that you
Coding Interview Patterns Your Personal Dijkstra's Algorithm to Landing Your Dream Job The goal of AlgoMonster is to help you get a job in the shortest amount of time possible in a data driven way We compiled datasets of tech interview problems and broke them down by patterns This way
Recursion Recursion is one of the most important concepts in computer science Simply speaking recursion is the process of a function calling itself Using a real life analogy imagine a scenario where you invite your friends to lunch https assets algo monster recursion jpg You first call Ben and ask
Want a Structured Path to Master System Design Too? Don’t Miss This!