Medium
题目描述
给你一个 m x n 矩阵 matrix ,请按照 螺旋顺序 ,返回矩阵中的所有元素。
示例 1:
输入:matrix = [[1,2,3],[4,5,6],[7,8,9]]
输出:[1,2,3,6,9,8,7,4,5]
示例 2:
输入:matrix = [[1,2,3,4],[5,6,7,8],[9,10,11,12]]
输出:[1,2,3,4,8,12,11,10,9,5,6,7]
提示:
m == matrix.lengthn == matrix[i].length1 <= m, n <= 10-100 <= matrix[i][j] <= 100
解题思路
解题思路
这道题要求按螺旋顺序遍历矩阵,核心思想是模拟螺旋过程。
方法一:边界收缩法(推荐)
螺旋遍历的规律是:右 → 下 → 左 → 上 循环进行,每完成一个方向的遍历就收缩对应的边界。
具体步骤:
- 定义四个边界:上边界
top、下边界bottom、左边界left、右边界right - 按照顺序遍历:
- 向右:从
left到right,遍历top行,然后top++ - 向下:从
top到bottom,遍历right列,然后right-- - 向左:从
right到left,遍历bottom行,然后bottom-- - 向上:从
bottom到top,遍历left列,然后left++
- 向右:从
- 每次遍历完一个方向后,检查是否还有未访问的元素
方法二:方向数组法
使用方向数组 directions = [[0,1], [1,0], [0,-1], [-1,0]] 表示右、下、左、上四个方向,配合访问标记数组,当遇到边界或已访问元素时转向。
边界收缩法更加直观且空间效率更高,是推荐解法。
代码实现
class Solution {
public:
vector<int> spiralOrder(vector<vector<int>>& matrix) {
vector<int> result;
if (matrix.empty() || matrix[0].empty()) return result;
int m = matrix.size(), n = matrix[0].size();
int top = 0, bottom = m - 1, left = 0, right = n - 1;
while (top <= bottom && left <= right) {
// 向右遍历
for (int j = left; j <= right; j++) {
result.push_back(matrix[top][j]);
}
top++;
// 向下遍历
for (int i = top; i <= bottom; i++) {
result.push_back(matrix[i][right]);
}
right--;
// 向左遍历(需要检查是否还有行)
if (top <= bottom) {
for (int j = right; j >= left; j--) {
result.push_back(matrix[bottom][j]);
}
bottom--;
}
// 向上遍历(需要检查是否还有列)
if (left <= right) {
for (int i = bottom; i >= top; i--) {
result.push_back(matrix[i][left]);
}
left++;
}
}
return result;
}
};
class Solution:
def spiralOrder(self, matrix: List[List[int]]) -> List[int]:
if not matrix or not matrix[0]:
return []
result = []
m, n = len(matrix), len(matrix[0])
top, bottom, left, right = 0, m - 1, 0, n - 1
while top <= bottom and left <= right:
# 向右遍历
for j in range(left, right + 1):
result.append(matrix[top][j])
top += 1
# 向下遍历
for i in range(top, bottom + 1):
result.append(matrix[i][right])
right -= 1
# 向左遍历(需要检查是否还有行)
if top <= bottom:
for j in range(right, left - 1, -1):
result.append(matrix[bottom][j])
bottom -= 1
# 向上遍历(需要检查是否还有列)
if left <= right:
for i in range(bottom, top - 1, -1):
result.append(matrix[i][left])
left += 1
return result
public class Solution {
public IList<int> SpiralOrder(int[][] matrix) {
var result = new List<int>();
if (matrix.Length == 0 || matrix[0].Length == 0) return result;
int m = matrix.Length, n = matrix[0].Length;
int top = 0, bottom = m - 1, left = 0, right = n - 1;
while (top <= bottom && left <= right) {
// 向右遍历
for (int j = left; j <= right; j++) {
result.Add(matrix[top][j]);
}
top++;
// 向下遍历
for (int i = top; i <= bottom; i++) {
result.Add(matrix[i][right]);
}
right--;
// 向左遍历(需要检查是否还有行)
if (top <= bottom) {
for (int j = right; j >= left; j--) {
result.Add(matrix[bottom][j]);
}
bottom--;
}
// 向上遍历(需要检查是否还有列)
if (left <= right) {
for (int i = bottom; i >= top; i--) {
result.Add(matrix[i][left]);
}
left++;
}
}
return result;
}
}
/**
* @param {number[][]} matrix
* @return {number[]}
*/
var spiralOrder = function(matrix) {
const result = [];
let top = 0, bottom = matrix.length - 1;
let left = 0, right = matrix[0].length - 1;
while (top <= bottom && left <= right) {
for (let col = left; col <= right; col++) {
result.push(matrix[top][col]);
}
top++;
for (let row = top; row <= bottom; row++) {
result.push(matrix[row][right]);
}
right--;
if (top <= bottom) {
for (let col = right; col >= left; col--) {
result.push(matrix[bottom][col]);
}
bottom--;
}
if (left <= right) {
for (let row = bottom; row >= top; row--) {
result.push(matrix[row][left]);
}
left++;
}
}
return result;
};
复杂度分析
| 复杂度类型 | 复杂度 | 说明 |
|---|---|---|
| 时间复杂度 | O(m × n) | 需要遍历矩阵中的每个元素一次 |
| 空间复杂度 | O(1) | 只使用了常数级别的额外空间(不计输出数组) |
相关题目
. Spiral Matrix II (Medium)
. Spiral Matrix III (Medium)
. Spiral Matrix IV (Medium)