title: Cells in a Range on an Excel Sheet
slug: cells-in-a-range-on-an-excel-sheet
difficulty: easy
leetcode_id: 2194
leetcode_url: https://leetcode.com/problems/cells-in-a-range-on-an-excel-sheet/
categories:
  - strings
  - arrays
patterns:
  - slug: matrix-traversal
    is_optimal: true

function_signature: "def cells_in_range(s: str) -> list[str]:"

test_cases:
  visible:
    - input: { s: "K1:L2" }
      expected: ["K1", "K2", "L1", "L2"]
    - input: { s: "A1:F1" }
      expected: ["A1", "B1", "C1", "D1", "E1", "F1"]
  hidden:
    - input: { s: "A1:A1" }
      expected: ["A1"]
    - input: { s: "A1:A3" }
      expected: ["A1", "A2", "A3"]
    - input: { s: "B2:D4" }
      expected: ["B2", "B3", "B4", "C2", "C3", "C4", "D2", "D3", "D4"]
    - input: { s: "Z1:Z9" }
      expected: ["Z1", "Z2", "Z3", "Z4", "Z5", "Z6", "Z7", "Z8", "Z9"]

description: |
  A cell `(r, c)` of an Excel sheet is represented as a string `"<col><row>"` where:

  - `<col>` denotes the column number `c` of the cell. It is represented by **alphabetical letters**. For example, the 1<sup>st</sup> column is denoted by `'A'`, the 2<sup>nd</sup> by `'B'`, the 3<sup>rd</sup> by `'C'`, and so on.
  - `<row>` is the row number `r` of the cell. The r<sup>th</sup> row is represented by the **integer** `r`.

  You are given a string `s` in the format `"<col1><row1>:<col2><row2>"`, where `<col1>` represents the column `c1`, `<row1>` represents the row `r1`, `<col2>` represents the column `c2`, and `<row2>` represents the row `r2`, such that `r1 <= r2` and `c1 <= c2`.

  Return *the **list of cells*** `(x, y)` *such that* `r1 <= x <= r2` *and* `c1 <= y <= c2`. The cells should be represented as **strings** in the format mentioned above and be sorted in **non-decreasing** order first by columns and then by rows.

constraints: |
  - `s.length == 5`
  - `'A' <= s[0] <= s[3] <= 'Z'`
  - `'1' <= s[1] <= s[4] <= '9'`
  - `s` consists of uppercase English letters, digits and `':'`

examples:
  - input: 's = "K1:L2"'
    output: '["K1","K2","L1","L2"]'
    explanation: "The cells K1, K2, L1, L2 form the rectangular range. The output is sorted by column first (K before L), then by row within each column."
  - input: 's = "A1:F1"'
    output: '["A1","B1","C1","D1","E1","F1"]'
    explanation: "All cells are in row 1, spanning columns A through F. Since there's only one row, the cells are simply ordered by column."

explanation:
  intuition: |
    Think of an Excel spreadsheet as a grid where columns are labelled with letters (A, B, C, ...) and rows with numbers (1, 2, 3, ...).

    When given a range like `"K1:L2"`, you're essentially asked to list all the cells in a rectangular region — starting from the top-left corner (K1) and ending at the bottom-right corner (L2).

    The key insight is that this is a **nested iteration** problem. The sorting requirement — first by columns, then by rows — tells us exactly how to iterate: the **outer loop** goes through columns (letters), and the **inner loop** goes through rows (numbers).

    Since columns are single uppercase letters in this problem, we can treat them as characters and iterate through their ASCII values. Similarly, rows are single digits, making extraction straightforward.

  approach: |
    We solve this using **Nested Iteration** over columns and rows:

    **Step 1: Parse the input string**

    - `s[0]`: Starting column (character)
    - `s[1]`: Starting row (character representing a digit)
    - `s[3]`: Ending column (character)
    - `s[4]`: Ending row (character representing a digit)

    &nbsp;

    **Step 2: Iterate through columns (outer loop)**

    - Loop from `s[0]` to `s[3]` inclusive
    - Use `chr()` and `ord()` to iterate through character codes
    - This ensures columns are processed in alphabetical order

    &nbsp;

    **Step 3: Iterate through rows (inner loop)**

    - For each column, loop from `s[1]` to `s[4]` inclusive
    - Convert row characters to integers for range iteration
    - Combine the column letter and row number to form the cell string

    &nbsp;

    **Step 4: Return the result**

    - The nested loop order naturally produces the required sorting (columns first, then rows)

  common_pitfalls:
    - title: Wrong Loop Order
      description: |
        A common mistake is iterating rows in the outer loop and columns in the inner loop.

        This would produce cells sorted by row first: `["K1", "L1", "K2", "L2"]` instead of the required `["K1", "K2", "L1", "L2"]`.

        Always read the sorting requirement carefully — "sorted first by columns and then by rows" means columns are the primary sort key.
      wrong_approach: "for row in rows: for col in cols"
      correct_approach: "for col in cols: for row in rows"

    - title: Off-by-One in Range
      description: |
        When using `range()` in Python, the end value is exclusive. If iterating from column `'K'` to `'L'`, using `range(ord('K'), ord('L'))` would miss `'L'`.

        Always add 1 to the end value: `range(ord(start_col), ord(end_col) + 1)`.
      wrong_approach: "range(ord(s[0]), ord(s[3]))"
      correct_approach: "range(ord(s[0]), ord(s[3]) + 1)"

    - title: Forgetting String Conversion
      description: |
        When building cell strings, remember that iterating with `range()` over rows gives integers, but column iteration with `chr(ord(...))` gives characters.

        Ensure both parts are converted to strings when concatenating: `col + str(row)` or using an f-string.

  key_takeaways:
    - "**Nested iteration order matters**: The loop structure directly determines the output order — outer loop = primary sort key"
    - "**Character arithmetic**: Use `ord()` and `chr()` to iterate through letter ranges, treating characters as their ASCII codes"
    - "**Fixed-format parsing**: When input has a guaranteed format (like `s.length == 5`), direct indexing is simpler than regex or split operations"
    - "**Excel-style coordinates**: A common pattern in grid problems — understand the column-letter, row-number convention"

  time_complexity: "O(m * n) where m is the number of columns and n is the number of rows in the range. We visit each cell exactly once."
  space_complexity: "O(m * n) to store the result list containing all cells in the range."

solutions:
  - approach_name: Nested Iteration
    is_optimal: true
    code: |
      def cells_in_range(s: str) -> list[str]:
          result = []

          # Extract start and end coordinates from fixed-format string
          start_col, start_row = s[0], s[1]
          end_col, end_row = s[3], s[4]

          # Outer loop: iterate through columns (letters)
          for col in range(ord(start_col), ord(end_col) + 1):
              # Inner loop: iterate through rows (numbers)
              for row in range(int(start_row), int(end_row) + 1):
                  # Combine column letter and row number
                  result.append(chr(col) + str(row))

          return result
    explanation: |
      **Time Complexity:** O(m * n) — We iterate through each cell in the rectangular range exactly once.

      **Space Complexity:** O(m * n) — The result list stores all cells in the range.

      The nested loop structure naturally produces the required sorting order. By iterating columns in the outer loop, we ensure cells are grouped by column first, then ordered by row within each column.

  - approach_name: List Comprehension
    is_optimal: true
    code: |
      def cells_in_range(s: str) -> list[str]:
          # Pythonic one-liner using nested list comprehension
          # Outer comprehension: columns, Inner: rows
          return [
              chr(col) + str(row)
              for col in range(ord(s[0]), ord(s[3]) + 1)
              for row in range(int(s[1]), int(s[4]) + 1)
          ]
    explanation: |
      **Time Complexity:** O(m * n) — Same as the iterative approach.

      **Space Complexity:** O(m * n) — The result list stores all cells.

      This is the same algorithm expressed as a list comprehension. The order of the `for` clauses matches the nested loop structure — columns first (outer), then rows (inner). This produces identical output in a more concise form.
