剑指offer19_顺时针打印矩阵_题解
顺时针打印矩阵
题目描述
输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字,例如,如果输入如下4 X 4矩阵: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 则依次打印出数字1,2,3,4,8,12,16,15,14,13,9,5,6,7,11,10.
示例1
输入
[[1,2],[3,4]]
返回值
[1,2,4,3]
分析
方案一:模拟
打印方向 | 1.根据边界打印 | 2.边界向内收缩 | 3.是否打印完毕 |
---|---|---|---|
从左到右 | 左边界l ,右边界 r |
上边界 t 加 1 |
是否 t > b |
从上到下 | 上边界 t ,下边界b |
右边界 r 减 1 |
是否 l > r |
从右到左 | 右边界 r ,左边界l |
下边界 b 减 1 |
是否 t > b |
从下到上 | 下边界 b ,上边界t |
左边界 l 加 1 |
左边界 l 加 1 |
/**
时间复杂度:O(MN)
M,N 分别为矩阵行数和列数。
空间复杂度:O(1)
四个边界 l , r , t , b 使用常数大小的 额外 空间( res 为必须使用的空间)。
**/
class Solution
{
public:
vector<int> printMatrix(vector<vector<int>> &matrix)
{
if (matrix.empty())
return {};
vector<int> res;
int l = 0; //左边界
int r = matrix[0].size() - 1; //右边界
int t = 0; //上边界
int b = matrix.size() - 1; //下边界
while (true)
{
//left->right
for (int i = l; i <= r; i++)
res.push_back(matrix[t][i]);
// 边界向内收缩
if (++t > b)
break;
//top->bottom
for (int i = t; i <= b; i++)
res.push_back(matrix[i][r]);
if (--r < l)
break;
//right->left
for (int i = r; i >= l; i--)
res.push_back(matrix[b][i]);
if (--b < t)
break;
//bottom->top
for (int i = b; i >= t; i--)
res.push_back(matrix[i][l]);
if (++l > r)
break;
}
return res;
}
};
方法二:按层模拟
/**
时间复杂度:O(mn),其中 m 和 n 分别是输入矩阵的行数和列数。矩阵中的每个元素都要被访问一次。
空间复杂度:O(1)。除了输出数组以外,空间复杂度是常数。
**/
class Solution
{
public:
vector<int> printMatrix(vector<vector<int>> &matrix)
{
if (matrix.empty())
return {};
int rows = matrix.size(), cols = matrix[0].size();
vector<int> order;
int left = 0, right = cols - 1, top = 0, bottom = rows - 1;
while (left <= right && top <= bottom)
{
//left->right
for (int i = left; i <= right; i++)
{
order.push_back(matrix[top][i]);
}
//top->bottom
for (int i = top + 1; i <= bottom; i++)
{
order.push_back(matrix[i][right]);
}
if (left < right && top < bottom)
{
//right->left
for (int i = right - 1; i > left; i--)
{
order.push_back(matrix[bottom][i]);
}
//bottom->top
for (int i = bottom; i > top; i--)
{
order.push_back(matrix[i][left]);
}
}
left++;
right--;
top++;
bottom--;
}
return order;
}
};