1、题目描述
输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字。
示例 1:
输入:matrix = [[1,2,3],[4,5,6],[7,8,9]]
输出:[1,2,3,6,9,8,7,4,5]
2、VS2019上运行
#include <iostream>
#include <vector>
using namespace std;
class Solution {
private:
static constexpr int directions[4][2] = { {0, 1}, {1, 0}, {0, -1}, {-1, 0} };
// 定义四个方向的偏移量,顺时针顺序为右、下、左、上
public:
//函数首先进行了一个边界检查,如果矩阵的行数或列数为0,则返回一个空的向量
vector<int> spiralOrder(vector<vector<int>>& matrix) {
if (matrix.size() == 0 || matrix[0].size() == 0) {
return {};
}
//获取矩阵的行数和列数
int rows = matrix.size(), columns = matrix[0].size();
vector<vector<bool>> visited(rows, vector<bool>(columns));
// 创建一个二维visited数组,用于标记元素是否已访问过
int total = rows * columns;
vector<int> order(total);
// 创建一个用于存储螺旋遍历顺序的数组,大小为矩阵中元素的总数
int row = 0, column = 0;
//向右(0)、向下(1)、向左(2)、向上(3)
int directionIndex = 0;
// 初始化起始行、列和方向索引
for (int i = 0; i < total; i++) {
order[i] = matrix[row][column];
visited[row][column] = true;
// 将当前位置的元素添加到遍历顺序数组中,并标记已访问
int nextRow = row + directions[directionIndex][0], nextColumn = column + directions[directionIndex][1];
// 计算下一个位置的行和列
if (nextRow < 0 || nextRow >= rows || nextColumn < 0 || nextColumn >= columns || visited[nextRow][nextColumn]) {
// 如果下一个位置超出界限或已经访问过,则改变方向
directionIndex = (directionIndex + 1) % 4;
}
row += directions[directionIndex][0];
column += directions[directionIndex][1];
// 更新行和列的值,继续遍历下一个位置
}
return order;
}
};
int main() {
Solution solution;
vector<vector<int>> matrix = { {1, 2, 3}, {4, 5, 6}, {7, 8, 9} };
vector<int> result = solution.spiralOrder(matrix);
cout << "Spiral order: ";
for (int num : result) {
cout << num << " ";
}
cout << endl;
return 0;
}
运行结果:
Spiral order: 1 2 3 6 9 8 7 4 5
3、一些解释
1. static constexpr int directions[4][2] = { {0, 1}, {1, 0}, {0, -1}, {-1, 0} };
这段代码定义了一个二维数组directions,包含了四个方向的偏移量。每个方向表示为一个长度为2的数组,第一个元素是行的偏移量,第二个元素是列的偏移量。
具体来说,directions数组中的四个元素分别表示:
{0, 1}:向右移动一列
{1, 0}:向下移动一行
{0, -1}:向左移动一列
{-1, 0}:向上移动一行
constexpr 是C++11引入的关键字,用于声明可以在编译时求值的常量表达式。它的作用是告诉编译器,在编译阶段就可以确定表达式的值,并在编译过程中将其替换为对应的常量值。这样可以提高程序的性能,并且允许在编译期进行更多的优化。在上面提到的代码中,constexpr用来声明了一个静态常量数组directions,这意味着在编译时,该数组将被直接计算,并直接存储在内存中。这样,在运行时每次访问directions数组时,不需要重新计算或分配内存,提高了运行时的性能。
2. directionIndex
在给定的代码中,directionIndex是一个整数变量,用于表示当前遍历的方向索引。在螺旋遍历矩阵时,我们需要按照一定的方向顺序访问矩阵中的元素。directionIndex的值可以是0、1、2、3,分别表示当前遍历方向的索引,顺时针顺序为向右(0)、向下(1)、向左(2)、向上(3)。当遍历到矩阵边界或已经访问过的元素时,directionIndex会被用来调整遍历方向。
在给定代码中的循环中,通过 directions[directionIndex] 来获取当前方向的偏移量,例如 directions[0] 表示向右偏移量,directions[1] 表示向下偏移量,以此类推。随着遍历的进行,当下一个位置超出矩阵边界或者已经被访问过时,可以通过 directionIndex = (directionIndex + 1) % 4 来改变方向,即将 directionIndex 增加1,并对4取余,确保在索引范围内循环变化。
总而言之,directionIndex 是一个用来表示当前遍历方向索引的变量,以调整螺旋遍历的方向。