Welcome to Subscribe On Youtube

54. Spiral Matrix

Description

Given an m x n matrix, return all elements of the matrix in spiral order.

 

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]

 

Constraints:

  • m == matrix.length
  • n == matrix[i].length
  • 1 <= m, n <= 10
  • -100 <= matrix[i][j] <= 100

Solutions

Solution 1: Simulation

We use $i$ and $j$ to represent the row and column of the current element, use $k$ to represent the current direction, and use an array or hash table $vis$ to record whether each element has been visited. Each time we visit an element, we mark it as visited, then move forward in the current direction. If we find that it is out of bounds or has been visited after moving forward, we change the direction and continue to move forward until the entire matrix is traversed.

The time complexity is $O(m \times n)$, and the space complexity is $O(m \times n)$. Here, $m$ and $n$ are the number of rows and columns of the matrix, respectively.

For visited elements, we can also add a constant $300$ to their values, so we don’t need an extra $vis$ array or hash table to record whether they have been visited, thereby reducing the space complexity to $O(1)$.

Solution 2: Layer-by-layer Simulation

We can also traverse and store the matrix elements from the outside to the inside, layer by layer.

The time complexity is $O(m \times n)$, and the space complexity is $O(1)$. Here, $m$ and $n$ are the number of rows and columns of the matrix, respectively.

Solution 2: Simulation (Space Optimization)

Notice that the range of matrix element values is $[-100, 100]$. Therefore, we can add a large value, such as $300$, to the visited elements. This way, we only need to check if the visited element is greater than $100$, without needing extra space to record whether it has been visited. If we need to restore the original values of the visited elements, we can traverse the matrix again after the traversal is complete and subtract $300$ from all elements.

The time complexity is $O(m \times n)$, where $m$ and $n$ are the number of rows and columns of the matrix, respectively. The space complexity is $O(1)$.

  • class Solution {
        public List<Integer> spiralOrder(int[][] matrix) {
            int m = matrix.length, n = matrix[0].length;
            int[] dirs = {0, 1, 0, -1, 0};
            int i = 0, j = 0, k = 0;
            List<Integer> ans = new ArrayList<>();
            boolean[][] vis = new boolean[m][n];
            for (int h = m * n; h > 0; --h) {
                ans.add(matrix[i][j]);
                vis[i][j] = true;
                int x = i + dirs[k], y = j + dirs[k + 1];
                if (x < 0 || x >= m || y < 0 || y >= n || vis[x][y]) {
                    k = (k + 1) % 4;
                }
                i += dirs[k];
                j += dirs[k + 1];
            }
            return ans;
        }
    }
    
    
    // Solution 2
    class Solution {
        public List<Integer> spiralOrder(int[][] matrix) {
            int m = matrix.length, n = matrix[0].length;
            int[] dirs = {0, 1, 0, -1, 0};
            int i = 0, j = 0, k = 0;
            List<Integer> ans = new ArrayList<>();
            for (int h = m * n; h > 0; --h) {
                ans.add(matrix[i][j]);
                matrix[i][j] += 300;
                int x = i + dirs[k], y = j + dirs[k + 1];
                if (x < 0 || x >= m || y < 0 || y >= n || matrix[i][j] > 100) {
                    k = (k + 1) % 4;
                }
                i += dirs[k];
                j += dirs[k + 1];
            }
            for (int i = 0; i < m; ++i) {
                for (int j = 0; j < n; ++j) {
                    matrix[i][j] -= 300;
                }
            }
            return ans;
        }
    }
    
    
  • class Solution {
    public:
        vector<int> spiralOrder(vector<vector<int>>& matrix) {
            int m = matrix.size(), n = matrix[0].size();
            int dirs[5] = {0, 1, 0, -1, 0};
            int i = 0, j = 0, k = 0;
            vector<int> ans;
            bool vis[m][n];
            memset(vis, false, sizeof(vis));
            for (int h = m * n; h; --h) {
                ans.push_back(matrix[i][j]);
                vis[i][j] = true;
                int x = i + dirs[k], y = j + dirs[k + 1];
                if (x < 0 || x >= m || y < 0 || y >= n || vis[x][y]) {
                    k = (k + 1) % 4;
                }
                i += dirs[k];
                j += dirs[k + 1];
            }
            return ans;
        }
    };
    
    
    // Solution 2
    class Solution {
    public:
        vector<int> spiralOrder(vector<vector<int>>& matrix) {
            int m = matrix.size(), n = matrix[0].size();
            int dirs[5] = {0, 1, 0, -1, 0};
            int i = 0, j = 0, k = 0;
            vector<int> ans;
            for (int h = m * n; h; --h) {
                ans.push_back(matrix[i][j]);
                matrix[i][j] += 300;
                int x = i + dirs[k], y = j + dirs[k + 1];
                if (x < 0 || x >= m || y < 0 || y >= n || matrix[x][y] > 100) {
                    k = (k + 1) % 4;
                }
                i += dirs[k];
                j += dirs[k + 1];
            }
            for (i = 0; i < m; ++i) {
                for (j = 0; j < n; ++j) {
                    matrix[i][j] -= 300;
                }
            }
            return ans;
        }
    };
    
    
  • class Solution:
        def spiralOrder(self, matrix: List[List[int]]) -> List[int]:
            m, n = len(matrix), len(matrix[0])
            dirs = (0, 1, 0, -1, 0)
            i = j = k = 0
            ans = []
            vis = set()
            for _ in range(m * n):
                ans.append(matrix[i][j])
                vis.add((i, j))
                x, y = i + dirs[k], j + dirs[k + 1]
                if not 0 <= x < m or not 0 <= y < n or (x, y) in vis:
                    k = (k + 1) % 4
                i = i + dirs[k]
                j = j + dirs[k + 1]
            return ans
    
    
    # Solution 2
    class Solution:
        def spiralOrder(self, matrix: List[List[int]]) -> List[int]:
            m, n = len(matrix), len(matrix[0])
            dirs = (0, 1, 0, -1, 0)
            i = j = k = 0
            ans = []
            for _ in range(m * n):
                ans.append(matrix[i][j])
                matrix[i][j] += 300
                x, y = i + dirs[k], j + dirs[k + 1]
                if x < 0 or x >= m or y < 0 or y >= n or matrix[x][y] > 100:
                    k = (k + 1) % 4
                i += dirs[k]
                j += dirs[k + 1]
            for i in range(m):
                for j in range(n):
                    matrix[i][j] -= 300
            return ans
    
    
  • func spiralOrder(matrix [][]int) (ans []int) {
    	m, n := len(matrix), len(matrix[0])
    	vis := make([][]bool, m)
    	for i := range vis {
    		vis[i] = make([]bool, n)
    	}
    	dirs := [5]int{0, 1, 0, -1, 0}
    	i, j, k := 0, 0, 0
    	for h := m * n; h > 0; h-- {
    		ans = append(ans, matrix[i][j])
    		vis[i][j] = true
    		x, y := i+dirs[k], j+dirs[k+1]
    		if x < 0 || x >= m || y < 0 || y >= n || vis[x][y] {
    			k = (k + 1) % 4
    		}
    		i, j = i+dirs[k], j+dirs[k+1]
    	}
    	return
    }
    
    
    // Solution 2
    func spiralOrder(matrix [][]int) (ans []int) {
    	m, n := len(matrix), len(matrix[0])
    	dirs := [5]int{0, 1, 0, -1, 0}
    	i, j, k := 0, 0, 0
    	for h := m * n; h > 0; h-- {
    		ans = append(ans, matrix[i][j])
    		matrix[i][j] += 300
    		x, y := i+dirs[k], j+dirs[k+1]
    		if x < 0 || x >= m || y < 0 || y >= n || matrix[x][y] > 100 {
    			k = (k + 1) % 4
    		}
    		i, j = i+dirs[k], j+dirs[k+1]
    	}
    	for i = 0; i < m; i++ {
    		for j = 0; j < n; j++ {
    			matrix[i][j] -= 300
    		}
    	}
    	return
    }
    
    
  • function spiralOrder(matrix: number[][]): number[] {
        const m = matrix.length;
        const n = matrix[0].length;
        const ans: number[] = [];
        const vis = new Array(m).fill(0).map(() => new Array(n).fill(false));
        const dirs = [0, 1, 0, -1, 0];
        for (let h = m * n, i = 0, j = 0, k = 0; h > 0; --h) {
            ans.push(matrix[i][j]);
            vis[i][j] = true;
            const x = i + dirs[k];
            const y = j + dirs[k + 1];
            if (x < 0 || x >= m || y < 0 || y >= n || vis[x][y]) {
                k = (k + 1) % 4;
            }
            i += dirs[k];
            j += dirs[k + 1];
        }
        return ans;
    }
    
    
    // Solution 2
    function spiralOrder(matrix: number[][]): number[] {
        const m = matrix.length;
        const n = matrix[0].length;
        const ans: number[] = [];
        const dirs = [0, 1, 0, -1, 0];
        for (let h = m * n, i = 0, j = 0, k = 0; h > 0; --h) {
            ans.push(matrix[i][j]);
            matrix[i][j] += 300;
            const x = i + dirs[k];
            const y = j + dirs[k + 1];
            if (x < 0 || x >= m || y < 0 || y >= n || matrix[x][y] > 100) {
                k = (k + 1) % 4;
            }
            i += dirs[k];
            j += dirs[k + 1];
        }
        for (let i = 0; i < m; ++i) {
            for (let j = 0; j < n; ++j) {
                matrix[i][j] -= 300;
            }
        }
        return ans;
    }
    
    
  • /**
     * @param {number[][]} matrix
     * @return {number[]}
     */
    var spiralOrder = function (matrix) {
        const m = matrix.length;
        const n = matrix[0].length;
        const ans = [];
        const vis = new Array(m).fill(0).map(() => new Array(n).fill(false));
        const dirs = [0, 1, 0, -1, 0];
        for (let h = m * n, i = 0, j = 0, k = 0; h > 0; --h) {
            ans.push(matrix[i][j]);
            vis[i][j] = true;
            const x = i + dirs[k];
            const y = j + dirs[k + 1];
            if (x < 0 || x >= m || y < 0 || y >= n || vis[x][y]) {
                k = (k + 1) % 4;
            }
            i += dirs[k];
            j += dirs[k + 1];
        }
        return ans;
    };
    
    
    // Solution 2
    /**
     * @param {number[][]} matrix
     * @return {number[]}
     */
    var spiralOrder = function (matrix) {
        const m = matrix.length;
        const n = matrix[0].length;
        const ans = [];
        const dirs = [0, 1, 0, -1, 0];
        for (let h = m * n, i = 0, j = 0, k = 0; h > 0; --h) {
            ans.push(matrix[i][j]);
            matrix[i][j] += 300;
            const x = i + dirs[k];
            const y = j + dirs[k + 1];
            if (x < 0 || x >= m || y < 0 || y >= n || matrix[x][y] > 100) {
                k = (k + 1) % 4;
            }
            i += dirs[k];
            j += dirs[k + 1];
        }
        for (let i = 0; i < m; ++i) {
            for (let j = 0; j < n; ++j) {
                matrix[i][j] -= 300;
            }
        }
        return ans;
    };
    
    
  • public class Solution {
        public IList<int> SpiralOrder(int[][] matrix) {
            int m = matrix.Length, n = matrix[0].Length;
            int[] dirs = new int[] {0, 1, 0, -1, 0};
            IList<int> ans = new List<int>();
            bool[,] visited = new bool[m, n];
            for (int h = m * n, i = 0, j = 0, k = 0; h > 0; --h) {
                ans.Add(matrix[i][j]);
                visited[i, j] = true;
                int x = i + dirs[k], y = j + dirs[k + 1];
                if (x < 0 || x >= m || y < 0 || y >= n || visited[x, y]) {
                    k = (k + 1) % 4;
                }
                i += dirs[k];
                j += dirs[k + 1];
            }
            return ans;
        }
    }
    
    
    // Solution 2
    public class Solution {
        public IList<int> SpiralOrder(int[][] matrix) {
            int m = matrix.Length, n = matrix[0].Length;
            int[] dirs = { 0, 1, 0, -1, 0 };
            int i = 0, j = 0, k = 0;
            IList<int> ans = new List<int>();
            for (int h = m * n; h > 0; --h) {
                ans.Add(matrix[i][j]);
                matrix[i][j] += 300;
                int x = i + dirs[k], y = j + dirs[k + 1];
                if (x < 0 || x >= m || y < 0 || y >= n || matrix[x][y] > 100) {
                    k = (k + 1) % 4;
                }
                i += dirs[k];
                j += dirs[k + 1];
            }
            for (int a = 0; a < m; ++a) {
                for (int b = 0; b < n; ++b) {
                    matrix[a][b] -= 300;
                }
            }
            return ans;
        }
    }
    
    
  • impl Solution {
        pub fn spiral_order(matrix: Vec<Vec<i32>>) -> Vec<i32> {
            let mut x1 = 0;
            let mut y1 = 0;
            let mut x2 = matrix.len() - 1;
            let mut y2 = matrix[0].len() - 1;
            let mut result = vec![];
    
            while x1 <= x2 && y1 <= y2 {
                for j in y1..=y2 {
                    result.push(matrix[x1][j]);
                }
                for i in x1 + 1..=x2 {
                    result.push(matrix[i][y2]);
                }
                if x1 < x2 && y1 < y2 {
                    for j in (y1..y2).rev() {
                        result.push(matrix[x2][j]);
                    }
                    for i in (x1 + 1..x2).rev() {
                        result.push(matrix[i][y1]);
                    }
                }
                x1 += 1;
                y1 += 1;
                if x2 != 0 {
                    x2 -= 1;
                }
                if y2 != 0 {
                    y2 -= 1;
                }
            }
            return result;
        }
    }
    
    
    // Solution 2
    impl Solution {
        pub fn spiral_order(mut matrix: Vec<Vec<i32>>) -> Vec<i32> {
            let m = matrix.len();
            let n = matrix[0].len();
            let mut dirs = vec![0, 1, 0, -1, 0];
            let mut i = 0;
            let mut j = 0;
            let mut k = 0;
            let mut ans = Vec::new();
    
            for _ in 0..(m * n) {
                ans.push(matrix[i][j]);
                matrix[i][j] += 300;
                let x = i as i32 + dirs[k] as i32;
                let y = j as i32 + dirs[k + 1] as i32;
    
                if x < 0
                    || x >= m as i32
                    || y < 0
                    || y >= n as i32
                    || matrix[x as usize][y as usize] > 100
                {
                    k = (k + 1) % 4;
                }
    
                i = (i as i32 + dirs[k] as i32) as usize;
                j = (j as i32 + dirs[k + 1] as i32) as usize;
            }
    
            for i in 0..m {
                for j in 0..n {
                    matrix[i][j] -= 300;
                }
            }
    
            ans
        }
    }
    
    

All Problems

All Solutions