Bird
Raised Fist0
Interview Prepmath-geometryeasyAmazonGoogleMicrosoft

Excel Sheet Column Number

Choose your preparation mode4 modes available
🎯
Excel Sheet Column Number
easyMATHAmazonGoogleMicrosoft

Imagine you are working with Excel and want to convert a column label like 'AB' into its corresponding column number to automate spreadsheet processing.

💡 This problem involves converting a string representing a base-26 number (with letters A-Z) into its decimal equivalent. Beginners often struggle because the encoding is not zero-based and requires careful handling of character values and positional weights.
📋
Problem Statement

Given a string columnTitle that represents the column title as appears in an Excel sheet, return its corresponding column number. Input: A string columnTitle consisting of uppercase English letters only. Output: An integer representing the column number.

1 ≤ length of columnTitle ≤ 7columnTitle consists only of uppercase English letters (A-Z)
💡
Example
Input"A"
Output1

A corresponds to 1 in base-26 encoding.

Input"AB"
Output28

A = 1, B = 2; so 1*26 + 2 = 28.

Input"ZY"
Output701

Z = 26, Y = 25; so 26*26 + 25 = 701.

  • Single letter 'Z' → 26
  • Longest input 'ZZZZZZZ' → large number within integer range
  • Input with all 'A's → minimum values for length
  • Input with mixed letters like 'AZ' → correct positional calculation
⚠️
Common Mistakes
Using zero-based indexing for letters (A=0 instead of A=1)

Results are off by one, producing incorrect column numbers

✅ Add +1 after subtracting 'A' from character code

Multiplying by 26 after adding the current character's value

Incorrect calculation order leads to wrong results

✅ Multiply the accumulated result by 26 before adding the current character's value

Using substring in recursion without considering time complexity

Leads to O(n^2) time and possible timeouts on large inputs

✅ Use iterative approach or pass indices to avoid substring overhead

Not handling empty string input

May cause runtime errors or incorrect output

✅ Add base case to return 0 or handle empty input explicitly

Assuming lowercase letters without conversion

Incorrect ASCII calculations and wrong results

✅ Convert input to uppercase or adjust calculations accordingly

🧠
Brute Force (Iterative Conversion with Multiplication)
💡 This approach directly simulates the base-26 conversion by iterating over each character and accumulating the result. It is straightforward and helps beginners understand the problem's core encoding.

Intuition

Treat the string as a base-26 number where 'A' maps to 1, 'B' to 2, ..., 'Z' to 26. Multiply the running total by 26 and add the current character's value.

Algorithm

  1. Initialize result to 0.
  2. Iterate over each character in the string from left to right.
  3. Convert the character to its numeric value (A=1, B=2, ..., Z=26).
  4. Update result = result * 26 + numeric value.
  5. Return the final result.
💡 The main challenge is remembering that each letter represents a digit in base-26 and that the value is 1-based, not zero-based.
</>
Code
def titleToNumber(columnTitle: str) -> int:
    result = 0
    for ch in columnTitle:
        value = ord(ch) - ord('A') + 1
        result = result * 26 + value
    return result

# Driver code
if __name__ == '__main__':
    test_cases = ['A', 'AB', 'ZY']
    for case in test_cases:
        print(f"{case} -> {titleToNumber(case)}")
Line Notes
result = 0Initialize accumulator to zero before processing characters
for ch in columnTitle:Process each character sequentially from left to right
value = ord(ch) - ord('A') + 1Convert character to 1-based numeric value
result = result * 26 + valueShift previous result by base 26 and add current digit
public class Solution {
    public int titleToNumber(String columnTitle) {
        int result = 0;
        for (char ch : columnTitle.toCharArray()) {
            int value = ch - 'A' + 1;
            result = result * 26 + value;
        }
        return result;
    }

    public static void main(String[] args) {
        Solution sol = new Solution();
        String[] tests = {"A", "AB", "ZY"};
        for (String test : tests) {
            System.out.println(test + " -> " + sol.titleToNumber(test));
        }
    }
}
Line Notes
int result = 0;Initialize the result accumulator
for (char ch : columnTitle.toCharArray())Iterate over each character in the input string
int value = ch - 'A' + 1;Convert character to its 1-based numeric value
result = result * 26 + value;Multiply accumulated result by 26 and add current value
#include <iostream>
#include <string>
using namespace std;

int titleToNumber(string columnTitle) {
    int result = 0;
    for (char ch : columnTitle) {
        int value = ch - 'A' + 1;
        result = result * 26 + value;
    }
    return result;
}

int main() {
    string tests[] = {"A", "AB", "ZY"};
    for (string test : tests) {
        cout << test << " -> " << titleToNumber(test) << endl;
    }
    return 0;
}
Line Notes
int result = 0;Initialize accumulator to zero
for (char ch : columnTitle)Loop through each character in the string
int value = ch - 'A' + 1;Convert character to 1-based numeric value
result = result * 26 + value;Update result by shifting and adding current digit
function titleToNumber(columnTitle) {
    let result = 0;
    for (let ch of columnTitle) {
        let value = ch.charCodeAt(0) - 'A'.charCodeAt(0) + 1;
        result = result * 26 + value;
    }
    return result;
}

// Test cases
const tests = ['A', 'AB', 'ZY'];
tests.forEach(test => console.log(`${test} -> ${titleToNumber(test)}`));
Line Notes
let result = 0;Initialize the result accumulator
for (let ch of columnTitle)Iterate over each character in the string
let value = ch.charCodeAt(0) - 'A'.charCodeAt(0) + 1;Convert character to 1-based numeric value
result = result * 26 + value;Multiply previous result by 26 and add current digit
⏱
Complexity
TimeO(n)
SpaceO(1)

We iterate through the string once, performing constant time operations per character.

💡 For a string of length 7 (max), this means at most 7 iterations, which is very efficient.
Interview Verdict: Accepted

This approach is efficient and accepted for all valid inputs, making it a solid baseline solution.

🧠
Recursive Approach
💡 This approach uses recursion to process the string from left to right, building the result by recursive calls. It helps understand the problem from a divide-and-conquer perspective.

Intuition

The column number for a string is 26 times the column number of the prefix (all but last character) plus the value of the last character.

Algorithm

  1. If the string is empty, return 0.
  2. Recursively compute the column number for the substring excluding the last character.
  3. Convert the last character to its numeric value.
  4. Return 26 * recursive result + last character's value.
💡 The recursion helps visualize how each character contributes based on its position from the right.
</>
Code
def titleToNumber(columnTitle: str) -> int:
    if not columnTitle:
        return 0
    last_char_value = ord(columnTitle[-1]) - ord('A') + 1
    return 26 * titleToNumber(columnTitle[:-1]) + last_char_value

# Driver code
if __name__ == '__main__':
    test_cases = ['A', 'AB', 'ZY']
    for case in test_cases:
        print(f"{case} -> {titleToNumber(case)}")
Line Notes
if not columnTitle:Base case: empty string returns 0
last_char_value = ord(columnTitle[-1]) - ord('A') + 1Convert last character to numeric value
return 26 * titleToNumber(columnTitle[:-1]) + last_char_valueCombine recursive result with last character's value
for case in test_cases:Test multiple inputs to verify correctness
public class Solution {
    public int titleToNumber(String columnTitle) {
        if (columnTitle.length() == 0) return 0;
        int lastCharValue = columnTitle.charAt(columnTitle.length() - 1) - 'A' + 1;
        return 26 * titleToNumber(columnTitle.substring(0, columnTitle.length() - 1)) + lastCharValue;
    }

    public static void main(String[] args) {
        Solution sol = new Solution();
        String[] tests = {"A", "AB", "ZY"};
        for (String test : tests) {
            System.out.println(test + " -> " + sol.titleToNumber(test));
        }
    }
}
Line Notes
if (columnTitle.length() == 0) return 0;Base case for recursion
int lastCharValue = columnTitle.charAt(columnTitle.length() - 1) - 'A' + 1;Get numeric value of last character
return 26 * titleToNumber(columnTitle.substring(0, columnTitle.length() - 1)) + lastCharValue;Recursive call and combine result
for (String test : tests)Loop through test cases to validate
#include <iostream>
#include <string>
using namespace std;

int titleToNumber(string columnTitle) {
    if (columnTitle.empty()) return 0;
    int lastCharValue = columnTitle.back() - 'A' + 1;
    return 26 * titleToNumber(columnTitle.substr(0, columnTitle.size() - 1)) + lastCharValue;
}

int main() {
    string tests[] = {"A", "AB", "ZY"};
    for (string test : tests) {
        cout << test << " -> " << titleToNumber(test) << endl;
    }
    return 0;
}
Line Notes
if (columnTitle.empty()) return 0;Base case for recursion
int lastCharValue = columnTitle.back() - 'A' + 1;Convert last character to numeric value
return 26 * titleToNumber(columnTitle.substr(0, columnTitle.size() - 1)) + lastCharValue;Recursive call and combine
for (string test : tests)Test multiple inputs for correctness
function titleToNumber(columnTitle) {
    if (columnTitle.length === 0) return 0;
    let lastCharValue = columnTitle.charCodeAt(columnTitle.length - 1) - 'A'.charCodeAt(0) + 1;
    return 26 * titleToNumber(columnTitle.slice(0, -1)) + lastCharValue;
}

// Test cases
const tests = ['A', 'AB', 'ZY'];
tests.forEach(test => console.log(`${test} -> ${titleToNumber(test)}`));
Line Notes
if (columnTitle.length === 0) return 0;Base case for recursion
let lastCharValue = columnTitle.charCodeAt(columnTitle.length - 1) - 'A'.charCodeAt(0) + 1;Convert last character to numeric value
return 26 * titleToNumber(columnTitle.slice(0, -1)) + lastCharValue;Recursive call and combine results
tests.forEach(test => console.log(...))Run test cases to verify correctness
⏱
Complexity
TimeO(n^2)
SpaceO(n)

Each recursive call creates a substring which is O(n), and there are n calls, leading to O(n^2) time. Space is O(n) due to recursion stack.

💡 For length 7, this is still manageable, but inefficient compared to iterative.
Interview Verdict: Accepted but inefficient

This approach works but is less efficient due to substring creation and recursion overhead.

🧠
Iterative Approach with Precomputed Powers (Optimization for Large Inputs)
💡 This approach precomputes powers of 26 to multiply each character's value by its positional weight, demonstrating an alternative way to think about the problem.

Intuition

Each character's contribution is its numeric value times 26 raised to the power of its position from the right.

Algorithm

  1. Compute powers of 26 for each position from right to left.
  2. Initialize result to 0.
  3. Iterate over the string from left to right.
  4. For each character, convert to numeric value and multiply by corresponding power.
  5. Sum all contributions and return the result.
💡 This approach explicitly calculates each character's positional value instead of accumulating progressively.
</>
Code
def titleToNumber(columnTitle: str) -> int:
    n = len(columnTitle)
    powers = [1] * n
    for i in range(n - 2, -1, -1):
        powers[i] = powers[i + 1] * 26
    result = 0
    for i, ch in enumerate(columnTitle):
        value = ord(ch) - ord('A') + 1
        result += value * powers[i]
    return result

# Driver code
if __name__ == '__main__':
    test_cases = ['A', 'AB', 'ZY']
    for case in test_cases:
        print(f"{case} -> {titleToNumber(case)}")
Line Notes
n = len(columnTitle)Store length for power array size
powers = [1] * nInitialize powers array with 1s
for i in range(n - 2, -1, -1)Compute powers of 26 from right to left
result += value * powers[i]Add weighted value of current character
public class Solution {
    public int titleToNumber(String columnTitle) {
        int n = columnTitle.length();
        int[] powers = new int[n];
        powers[n - 1] = 1;
        for (int i = n - 2; i >= 0; i--) {
            powers[i] = powers[i + 1] * 26;
        }
        int result = 0;
        for (int i = 0; i < n; i++) {
            int value = columnTitle.charAt(i) - 'A' + 1;
            result += value * powers[i];
        }
        return result;
    }

    public static void main(String[] args) {
        Solution sol = new Solution();
        String[] tests = {"A", "AB", "ZY"};
        for (String test : tests) {
            System.out.println(test + " -> " + sol.titleToNumber(test));
        }
    }
}
Line Notes
int n = columnTitle.length();Get length of input string
powers[n - 1] = 1;Initialize last power as 1
for (int i = n - 2; i >= 0; i--)Compute powers of 26 backwards
result += value * powers[i];Add weighted character value to result
#include <iostream>
#include <string>
#include <vector>
using namespace std;

int titleToNumber(string columnTitle) {
    int n = columnTitle.size();
    vector<int> powers(n, 1);
    for (int i = n - 2; i >= 0; i--) {
        powers[i] = powers[i + 1] * 26;
    }
    int result = 0;
    for (int i = 0; i < n; i++) {
        int value = columnTitle[i] - 'A' + 1;
        result += value * powers[i];
    }
    return result;
}

int main() {
    string tests[] = {"A", "AB", "ZY"};
    for (string test : tests) {
        cout << test << " -> " << titleToNumber(test) << endl;
    }
    return 0;
}
Line Notes
int n = columnTitle.size();Store string length
vector<int> powers(n, 1);Initialize vector for powers of 26
for (int i = n - 2; i >= 0; i--)Calculate powers from right to left
result += value * powers[i];Add weighted value of character
function titleToNumber(columnTitle) {
    const n = columnTitle.length;
    const powers = new Array(n).fill(1);
    for (let i = n - 2; i >= 0; i--) {
        powers[i] = powers[i + 1] * 26;
    }
    let result = 0;
    for (let i = 0; i < n; i++) {
        let value = columnTitle.charCodeAt(i) - 'A'.charCodeAt(0) + 1;
        result += value * powers[i];
    }
    return result;
}

// Test cases
const tests = ['A', 'AB', 'ZY'];
tests.forEach(test => console.log(`${test} -> ${titleToNumber(test)}`));
Line Notes
const n = columnTitle.length;Store length of input string
const powers = new Array(n).fill(1);Initialize array for powers of 26
for (let i = n - 2; i >= 0; i--)Compute powers from right to left
result += value * powers[i];Add weighted character value to result
⏱
Complexity
TimeO(n)
SpaceO(n)

We compute powers in O(n) and then iterate once more to calculate the result, so total O(n) time and O(n) space for powers array.

💡 This approach uses extra space but explicitly shows positional weights, which can help in understanding.
Interview Verdict: Accepted

This approach is correct and efficient but uses extra space compared to the first approach.

📊
All Approaches - One-Glance Tradeoffs
💡 The iterative approach (Approach 1) is the best choice for interviews due to its simplicity and efficiency.
ApproachTimeSpaceStack RiskReconstructUse In Interview
1. Brute Force (Iterative Conversion)O(n)O(1)NoN/ACode this approach for best balance of clarity and efficiency
2. Recursive ApproachO(n^2)O(n)Yes (deep recursion)N/AMention to show understanding, but avoid coding
3. Iterative with Precomputed PowersO(n)O(n)NoN/AGood to mention as an alternative, but not necessary to code
💼
Interview Strategy
💡 Use this guide to understand the problem deeply before interviews. Start with brute force to build intuition, then explore recursive and optimized methods. Practice coding and explaining each approach clearly.

How to Present

Step 1: Clarify the problem and constraints with the interviewer.Step 2: Describe the brute force iterative approach to convert the string to a number.Step 3: Discuss a recursive approach to show understanding of the problem structure.Step 4: Present the optimized approach with precomputed powers if time permits.Step 5: Code the chosen approach carefully and test with sample inputs.

Time Allocation

Clarify: 2min → Approach: 3min → Code: 5min → Test: 3min. Total ~13min

What the Interviewer Tests

The interviewer tests your understanding of base conversions, handling of character to number mapping, and ability to write clean, efficient code.

Common Follow-ups

  • How would you handle lowercase letters? → Convert to uppercase or adjust ASCII calculations.
  • What if the input is very long? → Discuss integer overflow and possible use of BigInteger or similar.
💡 These follow-ups test your ability to adapt the solution to variations and edge cases.
🔍
Pattern Recognition

When to Use

1) Input is a string representing a number in a non-standard base; 2) Characters map to digits with offset; 3) Need to convert to decimal integer; 4) Base is 26 with letters A-Z.

Signature Phrases

'Excel sheet column title''Convert column title to number''Base 26 encoding with letters'

NOT This Pattern When

Problems involving arbitrary string parsing without numeric base conversion

Similar Problems

Excel Sheet Column Title - inverse problem converting number to stringBase Conversion Problems - generalize to other basesNumber to String Encoding - encoding/decoding schemes

Practice

(1/5)
1. Consider the following code snippet that checks if a number is a palindrome by reversing half of its digits. What is the value of reversed_half after the second iteration of the while loop when input is 12321?
easy
A. 12
B. 1
C. 21
D. 123

Solution

  1. Step 1: Trace first iteration

    Initial x=12321, reversed_half=0 reversed_half = 0*10 + 12321%10 = 1 x = 12321 // 10 = 1232
  2. Step 2: Trace second iteration

    reversed_half = 1*10 + 1232%10 = 10 + 2 = 12 x = 1232 // 10 = 123
  3. Final Answer:

    Option A -> Option A
  4. Quick Check:

    After two iterations reversed_half is 12 [OK]
Hint: Track variable updates carefully each loop iteration [OK]
Common Mistakes:
  • Off-by-one iteration count
  • Mixing x and reversed_half values
  • Incorrect modulo or division
2. Given the following recursive reverse integer code, what is the final output when input is 120?
def reverse(x: int) -> int:
    INT_MAX = 2**31 - 1
    INT_MIN = -2**31
    sign = -1 if x < 0 else 1
    x = abs(x)

    def helper(num, rev):
        if num == 0:
            return rev
        pop = num % 10
        if rev > INT_MAX // 10 or (rev == INT_MAX // 10 and pop > 7):
            return 0
        return helper(num // 10, rev * 10 + pop)

    rev = helper(x, 0)
    return sign * rev if rev != 0 else 0

print(reverse(120))
easy
A. 0
B. 21
C. 12
D. 21

Solution

  1. Step 1: Trace helper calls for input 120

    helper(120,0) -> pop=0, helper(12,0*10+0=0) helper(12,0) -> pop=2, helper(1,0*10+2=2) helper(1,2) -> pop=1, helper(0,2*10+1=21) helper(0,21) returns 21
  2. Step 2: Apply sign and check overflow

    Input is positive, so final return is 21. No overflow detected.
  3. Final Answer:

    Option B -> Option B
  4. Quick Check:

    Reversed 120 is 21 after dropping trailing zero [OK]
Hint: Trailing zeros disappear after reversal [OK]
Common Mistakes:
  • Returning 12 by reversing digits incorrectly
  • Returning 0 due to wrong overflow check
  • Confusing pop digit order
3. What is the time complexity of the optimal approach that uses a hash set and checks pairs of points as diagonals to find the minimum area rectangle, given n points?
medium
A. O(n^4) because all quadruples of points are checked
B. O(n^2) because all pairs of points are checked and hash set lookups are O(1)
C. O(n^3) because for each pair, a linear search is done for complementary points
D. O(n log n) because points are sorted and then pairs are checked

Solution

  1. Step 1: Identify loops in the optimal approach

    The code iterates over all pairs of points (i,j), which is O(n^2).
  2. Step 2: Analyze point existence checks

    Checking if complementary points exist uses a hash set with O(1) average lookup, so no extra multiplicative factor.
  3. Final Answer:

    Option B -> Option B
  4. Quick Check:

    Double loop + O(1) lookup -> O(n^2) time [OK]
Hint: Pairs checked, hash lookups O(1) -> O(n^2) [OK]
Common Mistakes:
  • Confusing with brute force O(n^4)
  • Assuming linear search inside pairs causes O(n^3)
4. What is the time complexity of the optimal rectangle overlap check algorithm that uses min and max coordinate comparisons?
medium
A. O(1), constant time since only coordinate comparisons are done
B. O(n^2), checking all pairs of points between rectangles
C. O(log n), due to sorting of coordinates
D. O(n), where n is the number of points inside the rectangles

Solution

  1. Step 1: Identify operations performed

    The algorithm only performs a fixed number of min and max operations on rectangle coordinates.
  2. Step 2: Recognize no loops or recursion involved

    Since no iteration over points or sorting is done, the time complexity is constant.
  3. Final Answer:

    Option A -> Option A
  4. Quick Check:

    Only a few arithmetic and comparison operations -> O(1) [OK]
Hint: No loops or recursion means O(1) time [OK]
Common Mistakes:
  • Assuming complexity depends on rectangle size or points inside
  • Confusing coordinate comparisons with sorting
  • Thinking overlap check requires scanning all points
5. What is the time and space complexity of the recursive digit extraction approach to reverse a 32-bit signed integer with d digits?
medium
A. Time: O(d), Space: O(d) -- linear digit processing and recursion stack depth equals digit count
B. Time: O(d^2), Space: O(1) -- due to repeated multiplication and no recursion stack
C. Time: O(d), Space: O(1) -- linear digit processing with constant auxiliary space
D. Time: O(1), Space: O(d) -- constant time due to fixed integer size but recursion stack grows

Solution

  1. Step 1: Identify time complexity

    Each digit is processed once, so time is O(d) where d is number of digits.
  2. Step 2: Identify space complexity

    Recursive calls stack up to d levels, so space is O(d) due to recursion stack.
  3. Final Answer:

    Option A -> Option A
  4. Quick Check:

    Linear time and recursion stack space matches digit count [OK]
Hint: Recursion stack adds O(d) space [OK]
Common Mistakes:
  • Assuming constant space ignoring recursion stack
  • Confusing digit count with input size n
  • Thinking time is quadratic due to multiplication
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard