螺旋矩阵
题目要求
编写一个函数,该函数接收一个m x n
的矩阵matrix
作为输入参数。你需要按照顺时针螺旋的顺序遍历矩阵,并返回一个数组,该数组依次包含矩阵中的所有元素。
解题思路
解决这个问题的关键是确定矩阵遍历的边界,并且在遍历过程中逐步缩小这些边界。以下是解题的步骤:
-
初始化四个指标,分别代表当前遍历的上下左右边界:
top
(初始值为 0),bottom
(初始值为 m-1),left
(初始值为 0),right
(初始值为 n-1)。 -
创建一个空数组
result
,用于存放按顺时针螺旋顺序遍历的矩阵元素。 -
当
top
小于等于bottom
且left
小于等于right
时,执行以下步骤:a. 从左到右遍历上边界,即遍历
top
行的left
到right
列,遍历后top
增加 1,因为上边界已经遍历过了。b. 从上到下遍历右边界,即遍历
top
到bottom
行的right
列,遍历后right
减少 1,因为右边界已经遍历过了。c. 如果
top
仍然小于等于bottom
,则从右到左遍历下边界,即遍历bottom
行的right
到left
列,遍历后bottom
减少 1,因为下边界已经遍历过了。d. 如果
left
仍然小于等于right
,则从下到上遍历左边界,即遍历bottom
到top
行的left
列,遍历后left
增加 1,因为左边界已经遍历过了。 -
重复步骤 3,直到所有的边界都已经遍历过,即
top
大于bottom
或者left
大于right
。 -
返回
result
数组,该数组包含了按顺时针螺旋顺序遍历的矩阵元素。
这个方法的核心在于不断地缩小遍历的范围,并且在每一步中都要检查边界条件,以确保每个元素只被访问一次。
Golang 版本
package main
import "fmt"
func spiralOrder(matrix [][]int) []int {
if len(matrix) == 0 {
return []int{}
}
var result []int
top, bottom := 0, len(matrix)-1
left, right := 0, len(matrix[0])-1
for left <= right && top <= bottom {
// Traverse from left to right
for i := left; i <= right; i++ {
result = append(result, matrix[top][i])
}
top++
// Traverse downwards
for i := top; i <= bottom; i++ {
result = append(result, matrix[i][right])
}
right--
// Make sure we are now on a different row
if top <= bottom {
// Traverse from right to left
for i := right; i >= left; i-- {
result = append(result, matrix[bottom][i])
}
bottom--
}
// Make sure we are now on a different column
if left <= right {
// Traverse upwards
for i := bottom; i >= top; i-- {
result = append(result, matrix[i][left])
}
left++
}
}
return result
}
func main() {
matrix := [][]int{
{1, 2, 3},
{4, 5, 6},
{7, 8, 9},
}
result := spiralOrder(matrix)
fmt.Println(result)
}
这段代码定义了一个spiralOrder
函数,它接收一个二维整数数组matrix
,并返回一个一维整数数组,包含按顺时针螺旋顺序遍历的矩阵元素。main
函数中给出了一个示例矩阵,并打印出了spiralOrder
函数的结果。
C++版本
#include <iostream>
#include <vector>
std::vector<int> spiralOrder(const std::vector<std::vector<int>>& matrix) {
std::vector<int> result;
if (matrix.empty()) return result;
int top = 0, bottom = matrix.size() - 1;
int left = 0, right = matrix[0].size() - 1;
while (left <= right && top <= bottom) {
// Traverse from left to right
for (int i = left; i <= right; ++i) {
result.push_back(matrix[top][i]);
}
++top;
// Traverse downwards
for (int i = top; i <= bottom; ++i) {
result.push_back(matrix[i][right]);
}
--right;
if (top <= bottom) {
// Traverse from right to left
for (int i = right; i >= left; --i) {
result.push_back(matrix[bottom][i]);
}
--bottom;
}
if (left <= right) {
// Traverse upwards
for (int i = bottom; i >= top; --i) {
result.push_back(matrix[i][left]);
}
++left;
}
}
return result;
}
int main() {
std::vector<std::vector<int>> matrix = {
{1, 2, 3},
{4, 5, 6},
{7, 8, 9}
};
std::vector<int> result = spiralOrder(matrix);
for (int num : result) {
std::cout << num << " ";
}
std::cout << std::endl;
return 0;
}
这段 C++代码定义了一个spiralOrder
函数,它接收一个二维整数向量matrix
作为参数,并返回一个一维整数向量,包含按顺时针螺旋顺序遍历的矩阵元素。main
函数中给出了一个示例矩阵,并打印出了spiralOrder
函数的结果。
Python 版本
def spiralOrder(matrix):
if not matrix or not matrix[0]:
return []
result = []
top, bottom, left, right = 0, len(matrix) - 1, 0, len(matrix[0]) - 1
while left <= right and top <= bottom:
# Traverse from left to right
for i in range(left, right + 1):
result.append(matrix[top][i])
top += 1
# Traverse downwards
for i in range(top, bottom + 1):
result.append(matrix[i][right])
right -= 1
if top <= bottom:
# Traverse from right to left
for i in range(right, left - 1, -1):
result.append(matrix[bottom][i])
bottom -= 1
if left <= right:
# Traverse upwards
for i in range(bottom, top - 1, -1):
result.append(matrix[i][left])
left += 1
return result
# Example usage:
matrix = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9]
]
print(spiralOrder(matrix))
这段 Python 代码定义了一个spiralOrder
函数,它接收一个二维列表matrix
作为参数,并返回一个列表,包含按顺时针螺旋顺序遍历的矩阵元素。代码中还包含了一个示例矩阵,并打印出了spiralOrder
函数的结果。
Java 版本
import java.util.ArrayList;
import java.util.List;
public class SpiralMatrix {
public List<Integer> spiralOrder(int[][] matrix) {
List<Integer> result = new ArrayList<>();
if (matrix.length == 0) return result;
int top = 0, bottom = matrix.length - 1;
int left = 0, right = matrix[0].length - 1;
while (left <= right && top <= bottom) {
// Traverse from left to right
for (int i = left; i <= right; i++) {
result.add(matrix[top][i]);
}
top++;
// Traverse downwards
for (int i = top; i <= bottom; i++) {
result.add(matrix[i][right]);
}
right--;
if (top <= bottom) {
// Traverse from right to left
for (int i = right; i >= left; i--) {
result.add(matrix[bottom][i]);
}
bottom--;
}
if (left <= right) {
// Traverse upwards
for (int i = bottom; i >= top; i--) {
result.add(matrix[i][left]);
}
left++;
}
}
return result;
}
public static void main(String[] args) {
SpiralMatrix sm = new SpiralMatrix();
int[][] matrix = {
{1, 2, 3},
{4, 5, 6},
{7, 8, 9}
};
List<Integer> result = sm.spiralOrder(matrix);
for (int num : result) {
System.out.print(num + " ");
}
}
}
这段 Java 代码定义了一个SpiralMatrix
类,其中包含了一个spiralOrder
方法,它接收一个二维整数数组matrix
作为参数,并返回一个整数列表,包含按顺时针螺旋顺序遍历的矩阵元素。main
方法中给出了一个示例矩阵,并打印出了spiralOrder
方法的结果。
Rust 版本
fn spiral_order(matrix: Vec<Vec<i32>>) -> Vec<i32> { if matrix.is_empty() || matrix[0].is_empty() { return Vec::new(); } let mut result = Vec::new(); let (mut top, mut bottom) = (0, matrix.len() - 1); let (mut left, mut right) = (0, matrix[0].len() - 1); while left <= right && top <= bottom { // Traverse from left to right for i in left..=right { result.push(matrix[top][i]); } top += 1; // Traverse downwards if top <= bottom { for i in top..=bottom { result.push(matrix[i][right]); } right -= 1; } // Traverse from right to left if left <= right && top <= bottom { for i in (left..=right).rev() { result.push(matrix[bottom][i]); } bottom -= 1; } // Traverse upwards if top <= bottom { for i in (top..=bottom).rev() { result.push(matrix[i][left]); } left += 1; } } result } fn main() { let matrix = vec![ vec![1, 2, 3], vec![4, 5, 6], vec![7, 8, 9], ]; let order = spiral_order(matrix); for num in order { print!("{} ", num); } }
这段 Rust 代码定义了一个spiral_order
函数,它接收一个二维 i32 向量matrix
作为参数,并返回一个 i32 向量,包含按顺时针螺旋顺序遍历的矩阵元素。main
函数中给出了一个示例矩阵,并打印出了spiral_order
函数的结果。
总结
上述代码提供了一个螺旋遍历二维矩阵的算法实现。无论是在 C++、Python、Java 还是 Rust 中,核心逻辑是相同的,主要步骤如下:
-
初始化四个指针,分别代表矩阵的上边界
top
、下边界bottom
、左边界left
和右边界right
。 -
使用一个循环,按照从左到右、从上到下、从右到左、从下到上的顺序遍历矩阵的边界,并逐步缩小边界范围。
-
在每一步遍历中,将遍历到的元素添加到结果列表中。
-
每完成一次边界的遍历后,根据遍历的方向更新对应的边界指针。
-
当左边界超过右边界或上边界超过下边界时,结束遍历。
这个算法的时间复杂度是 O(N),其中 N 是矩阵中元素的总数,因为每个元素都被访问一次。空间复杂度是 O(N),用于存储结果的空间。
不同编程语言的实现细节可能略有不同,例如在边界条件的检查和索引的更新上,但整体算法框架是一致的。