<h2>解题思路:\n\n根据题目示例 <code>matrix = [[1,2,3],[4,5,6],[7,8,9]]</code> 的对应输出 <code>[1,2,3,6,9,8,7,4,5]</code> 可以发现,顺时针打印矩阵的顺序是 <strong>“从左向右、从上向下、从右向左、从下向上”</strong> 循环。\n\n因此,考虑设定矩阵的 “左、上、右、下” 四个边界,模拟以上矩阵遍历顺序。\n</h2>
<p><img src="https://pic.leetcode-cn.com/7605d807782923e4ad3c7995dc2485f538f202ac326bb330fe997f449123a548-Picture1.png" alt="Picture1.png" />{:width=400}\n</p>
<h3>算法流程:\n\n1. <strong>空值处理:</strong> 当 <code>matrix</code> 为空时,直接返回空列表 <code>[]</code> 即可。\n2. <strong>初始化:</strong> 矩阵 左、右、上、下 四个边界 <code>l</code> , <code>r</code> , <code>t</code> , <code>b</code> ,用于打印的结果列表 <code>res</code> 。\n3. <strong>循环打印:</strong> “从左向右、从上向下、从右向左、从下向上” 四个方向循环打印。\n 1. 根据边界打印,即将元素按顺序添加至列表 <code>res</code> 尾部。\n 2. 边界向内收缩 1 (代表已被打印)。\n 3. 判断边界是否相遇(是否打印完毕),若打印完毕则跳出。\n4. <strong>返回值:</strong> 返回 <code>res</code> 即可。\n</h3>
<p>| 打印方向 | 1. 根据边界打印 | 2. 边界向内收缩 | 3. 是否打印完毕 |\n| -------- | ---------------------- | ----------------- | --------------- |\n| 从左向右 | 左边界<code>l</code> ,右边界 <code>r</code> | 上边界 <code>t</code> 加 $1$ | 是否 <code>t > b</code> |\n| 从上向下 | 上边界 <code>t</code> ,下边界<code>b</code> | 右边界 <code>r</code> 减 $1$ | 是否 <code>l > r</code> |\n| 从右向左 | 右边界 <code>r</code> ,左边界<code>l</code> | 下边界 <code>b</code> 减 $1$ | 是否 <code>t > b</code> |\n| 从下向上 | 下边界 <code>b</code> ,上边界<code>t</code> | 左边界 <code>l</code> 加 $1$ | 是否 <code>l > r</code> |\n
<<img src="https://pic.leetcode-cn.com/1ad0fe88d15dc87643435eb7a17b368191725a44da4596722977e5798ace5b62-Picture2.png" alt="Picture2.png" />,<img src="https://pic.leetcode-cn.com/193444cbca5529fcd1bafec33ef576fe1309690be2c0110de05868f4415a8723-Picture3.png" alt="Picture3.png" />,<img src="https://pic.leetcode-cn.com/bca38a428306cb2aacc00513821e74150947ba241d9b7199bcad6c7e843a0105-Picture4.png" alt="Picture4.png" />,<img src="https://pic.leetcode-cn.com/e5de1e07957417f13d9fae22e6fb18dd5331b50258f0297f00ba57d25651df4a-Picture5.png" alt="Picture5.png" />,<img src="https://pic.leetcode-cn.com/2fde8dcd1481e390532995c02d3575ec9675a27390513c1540f40431dad7997a-Picture6.png" alt="Picture6.png" />,<img src="https://pic.leetcode-cn.com/1950d4c8ab6b09b62b7d5900ece4d8d4be882abebd2417a3030d172aedbc304e-Picture7.png" alt="Picture7.png" />>\n</p>
<h2>代码:\n\nJava, C++ 代码利用了 <code>++</code> 操作的便利性,详情可见 <a href="https://www.jianshu.com/p/b62eac216499">++i 和 i++ 的区别</a> 。\n</h2>
<ul>
<li><code>res[x++]</code> 等价于先给 <code>res[x]</code> 赋值,再给 <code>x</code> 自增 $1$ 。\n- <code>++t > b</code> 等价于先给 <code>t</code> 自增 $1$ ,再判断 <code>t > b</code> 逻辑表达式。\n</li>
</ul>
<blockquote>
<p>TIPS: 请注意区分数字 <code>1</code> 和字母 <code>l</code> 。\n</p>
</blockquote>
<pre><code class="language-Python"> t += 1
if t > b: break
for i in range(t, b + 1): res.append(matrix[i][r]) # top to bottom
r -= 1
if l > r: break
for i in range(r, l - 1, -1): res.append(matrix[b][i]) # right to left
b -= 1
if t > b: break
for i in range(b, t - 1, -1): res.append(matrix[i][l]) # bottom to top
l += 1
if l > r: break
return res
```\n
```Java []\nclass Solution {\n public List<Integer> spiralOrder(int[][] matrix) {\n if (matrix.length == 0)\n return new ArrayList<Integer>();\n int l = 0, r = matrix[0].length - 1, t = 0, b = matrix.length - 1, x = 0;\n Integer[] res = new Integer[(r + 1) * (b + 1)];\n while (true) {\n for (int i = l; i <= r; i++) res[x++] = matrix[t][i]; // left to right
if (++t > b) break;\n for (int i = t; i <= b; i++) res[x++] = matrix[i][r]; // top to bottom
if (l > --r) break;\n for (int i = r; i >= l; i--) res[x++] = matrix[b][i]; // right to left
if (t > --b) break;\n for (int i = b; i >= t; i--) res[x++] = matrix[i][l]; // bottom to top
if (++l > r) break;\n }\n return Arrays.asList(res);\n }\n}\n```\n
```C++ []\nclass Solution {\npublic:\n vector<int> spiralOrder(vector<vector<int>>& matrix) {\n if (matrix.empty()) return {};\n int l = 0, r = matrix[0].size() - 1, t = 0, b = matrix.size() - 1;\n vector<int> res;\n while (true) {\n for (int i = l; i <= r; i++) res.push_back(matrix[t][i]); // left to right
if (++t > b) break;\n for (int i = t; i <= b; i++) res.push_back(matrix[i][r]); // top to bottom
if (l > --r) break;\n for (int i = r; i >= l; i--) res.push_back(matrix[b][i]); // right to left
if (t > --b) break;\n for (int i = b; i >= t; i--) res.push_back(matrix[i][l]); // bottom to top
if (++l > r) break;\n }\n return res;\n }\n};\n```\n
### 复杂度分析:\n
- **时间复杂度 $O(MN)$ :** $M, N$ 分别为矩阵行数和列数。\n- **空间复杂度 $O(1)$ :** 四个边界 `l` , `r` , `t` , `b` 使用常数大小的额外空间。\n
---\n
[](https://leetcode.cn/studyplan/selected-coding-interview/)\n\n本学习计划配有代码仓,内含测试样例与数据结构封装,便于本地调试。可前往我的[个人主页](https://leetcode.cn/u/jyd/)获取。\n
</code></pre>