Taro Logo

Spiral Matrix

Medium
4 views
6 years ago

Given a 2D matrix (a list of lists) of integers, write a function that prints out the elements of the matrix in a spiral order. The spiral order starts from the top-left corner, moves to the right, then down, then left, and finally up, and repeats this process until all elements have been visited. The function should take the matrix as input and print the elements to the console separated by spaces.

Here are a few examples to illustrate the expected behavior:

  • Example 1:

    Input: matrix = [ [1, 2, 3], [4, 5, 6], [7, 8, 9] ]

    Output: 1 2 3 6 9 8 7 4 5

  • Example 2:

    Input: matrix = [ [1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12] ]

    Output: 1 2 3 4 8 12 11 10 9 5 6 7

  • Example 3:

    Input: matrix = [ [1, 2], [3, 4] ]

    Output: 1 2 4 3

  • Example 4:

    Input: matrix = [ [1] ]

    Output: 1

  • Example 5:

    Input: matrix = []

    Output: (empty output)

Your task is to implement a function, in the language of your choice, that correctly prints the spiral traversal of any given matrix. Please consider edge cases such as empty matrices or matrices with only one row or column.

Sample Answer

Spiral Matrix

Let's tackle the spiral matrix problem. The goal is to traverse a 2D matrix in a spiral order and return the elements in that order.

1. Naive (Brute Force) Solution

A brute-force approach would involve manually managing the boundaries of the matrix and directions. We would have variables to represent the top, bottom, left, and right boundaries. Then, we'd iterate in a specific direction (right, down, left, up), updating the boundaries and changing directions when we hit a boundary.

This solution works, but it is not optimal because it requires many conditional checks and manual management of the boundaries and directions. It can be quite verbose and error-prone.

2. Optimal Solution

The optimal solution builds on the same core idea of boundaries but aims for cleaner code and better readability. It still iterates through layers of the matrix.

Here's a conceptual outline:

  1. Initialize top, bottom, left, and right boundaries.
  2. While left <= right and top <= bottom:
    • Traverse from left to right along the top row.
    • Increment top.
    • Traverse from top to bottom along the right column.
    • Decrement right.
    • Check if top <= bottom and left <= right (to avoid duplicate printing for non-square matrices).
    • Traverse from right to left along the bottom row.
    • Decrement bottom.
    • Traverse from bottom to top along the left column.
    • Increment left.

3. Big(O) Run-time

The algorithm visits each element of the matrix exactly once. Therefore, the time complexity is O(m * n), where 'm' is the number of rows and 'n' is the number of columns in the matrix.

4. Big(O) Space Usage

We are only using a constant amount of extra space to store the boundaries and the result list. Therefore, the space complexity is O(1) excluding the space used to store the output list. If we include the output list, the space complexity is O(m*n) as we're storing every element of the input matrix into our output.

5. Edge Cases

  • Empty Matrix: If the input matrix is empty (either 0 rows or 0 columns), we should return an empty list.
  • Single Row/Column Matrix: The algorithm should correctly handle matrices with only one row or one column. The conditional top <= bottom and left <= right is important for handling these scenarios to avoid duplicate entries.
  • Non-Square Matrix: The algorithm must handle non-square matrices correctly, meaning m != n. The extra checks ensure it processes only unique elements.
  • Null Matrix: The input matrix should be validated for null values.

6. Code (Python)

pythondef spiral_matrix(matrix): if not matrix or not matrix[0]: return [] result = [] top, bottom = 0, len(matrix) - 1 left, right = 0, len(matrix[0]) - 1 while left <= right and top <= bottom: # Traverse right for i in range(left, right + 1): result.append(matrix[top][i]) top += 1 # Traverse down for i in range(top, bottom + 1): result.append(matrix[i][right]) right -= 1 if top <= bottom and left <= right: # Traverse left for i in range(right, left - 1, -1): result.append(matrix[bottom][i]) bottom -= 1 # Traverse up for i in range(bottom, top - 1, -1): result.append(matrix[i][left]) left += 1 return result

This code first handles the empty matrix edge case. It then initializes the boundaries and enters the main loop. Inside the loop, it traverses each side of the current layer and updates the boundaries accordingly. The additional checks if top <= bottom and left <= right: are critical to avoid duplicate entries in non-square matrices after the top and right traversals.