力扣螺旋矩阵系列总结(C++)
创始人
2024-06-03 11:29:38
0

tags: DSA C++ LeetCode Python

写在前面

螺旋矩阵系列, 严格来说不算双指针, 但是其中蕴含的思想很像双指针. (应该叫四指针)

  1. 54. 螺旋矩阵 - 力扣(LeetCode);(需要四个指针分别在需要转弯的时候移动)
  2. 59. 螺旋矩阵 II - 力扣(LeetCode);(跟上面的题异曲同工)
  3. 885. 螺旋矩阵 III - 力扣(LeetCode);(不需要考虑边界直接模拟, 注意这个题是从内往外转, 需要定义方向数组)
  4. 2326. 螺旋矩阵 IV - 力扣(LeetCode);(同基本的螺旋矩阵, 加上链表向后遍历的基本操作即可)

螺旋矩阵I

只能说, 用Python不讲武德:

def spiralOrder(self, matrix: List[List[int]]) -> List[int]:res = []while matrix:# 削头(第一层)res += matrix.pop(0)# 将剩下的逆时针转九十度,等待下次被削matrix = list(zip(*matrix))[::-1]return res

C++的写法很简练, 思路直接在代码中体现出来了. 四个变量逐次更新.

class Solution {
public:vector spiralOrder(vector>& matrix) {int m = matrix.size(), n = matrix[0].size(), SIZE = m * n;int l{}, r{n - 1}, t{}, b{m - 1}, i{}, x{}, y{};vector ans(SIZE);while (i < SIZE) {while (y <= r && i < SIZE) ans[i++] = matrix[t][y++];++t, x = t;while (x <= b && i < SIZE) ans[i++] = matrix[x++][r];--r, y = r;while (y >= l && i < SIZE) ans[i++] = matrix[b][y--];--b, x = b;while (x >= t && i < SIZE) ans[i++] = matrix[x--][l];++l, y = l;}return ans;}
};
// 用for循环也一样: 可能看起来简练一些
class Solution {
public:vector spiralOrder(vector>& matrix) {int m = matrix.size(), n = matrix[0].size(), SIZE = m * n;int l{}, r{n - 1}, t{}, b{m - 1}, i{}, x{}, y{};vector ans(SIZE);while (i < SIZE) {for (y = l; y <= r && i < SIZE; ++y) ans[i++] = matrix[t][y];++t;for (x = t; x <= b && i < SIZE; ++x) ans[i++] = matrix[x][r];--r;for (y = r; y >= l && i < SIZE; --y) ans[i++] = matrix[b][y];--b;for (x = b; x >= t && i < SIZE; --x) ans[i++] = matrix[x][l];++l;}return ans;}
};

或者用一种定义方向数组的写法, 算是一种模板了.

class Solution {
public:vector spiralOrder(vector>& matrix) {int m = matrix.size(), n = matrix[0].size(), SIZE = m * n;// 方向: 右下左上int dirs[4][2] {{0, 1}, {1, 0}, {0, -1}, {-1, 0}};int k{}, r{}, c{}, d{}, i{}, j{};vector ans(SIZE);while (k < SIZE) {ans[k++] = matrix[i][j];matrix[i][j] = 101; // 标记遍历过r = i + dirs[d][0], c = j + dirs[d][1];// 换向            if (r < 0 || r >= m || c < 0 || c >= n || matrix[r][c] == 101)d = (d + 1) % 4, r = i + dirs[d][0], c = j + dirs[d][1];i = r, j = c;}return ans;}
};

螺旋矩阵II

第一题代码改改还能用:

class Solution {
public:vector> generateMatrix(int n) {int SIZE = n * n;int l{}, r{n - 1}, t{}, b{n - 1}, i{1}, x{}, y{};vector> ans(n, vector(n));while (i <= SIZE) {for (y = l; y <= r; ++y) ans[t][y] = i++;++t;for (x = t; x <= b; ++x) ans[x][r] = i++;--r;for (y = r; y >= l; --y) ans[b][y] = i++;--b;for (x = b; x >= t; --x) ans[x][l] = i++;++l;}return ans;}
};

定义方向数组的方法: (不容易想, 但是代码相对简洁)

class Solution {
public:vector> generateMatrix(int n) {int SIZE = n * n, k{1};// 方向: 右下左上int dirs[4][2]{{0, 1}, {1, 0}, {0, -1}, {-1, 0}};int r{}, c{}, d{}, i{}, j{};vector> ans(n, vector(n));while (k <= SIZE) {ans[i][j] = k++;r = i + dirs[d][0], c = j + dirs[d][1];// 换向if (r < 0 || r >= n || c < 0 || c >= n || ans[r][c])d = (d + 1) % 4, r = i + dirs[d][0], c = j + dirs[d][1];i = r, j = c;}return ans;}
};

螺旋矩阵III

这个题和1,2,4不太一样, 原因在于旋转是由内而外的了, 这就要考虑一下边界情况了.

用定义四个方向数组的方法套模板就可以.

class Solution {
public:vector> spiralMatrixIII(int rows, int cols, int rStart,int cStart) {int dirs[4][2]{{0, 1}, {1, 0}, {0, -1}, {-1, 0}}; // 顺时针, 右下左上int SIZE = rows * cols, i{1}, steps{}, r{rStart}, c{cStart},d{};vector> ans(rows * cols);ans[0] = {r, c};while (i < SIZE) {++steps;// 每旋转两个方向, 就要增加一次单向距离for (int p{}; p < 2; ++p) {for (int j{}; j < steps; ++j) {auto& [rx, cx] = dirs[d]; // C++17r += rx, c += cx;if (r >= 0 && r < rows && c >= 0 && c < cols)ans[i++] = {r, c};}d = (d + 1) % 4;}}return ans;}
};

螺旋矩阵IV

熟悉一下链表的遍历, 这道题就会了. 直接用第一题代码.

class Solution {
public:vector> spiralMatrix(int m, int n, ListNode* head) {vector> ans(m, vector(n, -1));int t{}, l{}, r{n - 1}, b{m - 1}, i{}, j{};while (head) {for (j = l; j <= r && head; ++j, head = head->next)ans[t][j] = head->val;++t;for (i = t; i <= b && head; ++i, head = head->next)ans[i][r] = head->val;--r;for (j = r; j >= l && head; --j, head = head->next)ans[b][j] = head->val;--b;for (i = b; i >= t && head; --i, head = head->next)ans[i][l] = head->val;++l;}return ans;}
};

方向数组版:

class Solution {
public:vector> spiralMatrix(int m, int n, ListNode* head) {// 方向: 右下左上int dirs[4][2]{{0, 1}, {1, 0}, {0, -1}, {-1, 0}};int r{}, c{}, d{}, i{}, j{};vector> ans(m, vector(n, -1));while (head) {ans[i][j] = head->val, head = head->next;r = i + dirs[d][0], c = j + dirs[d][1];// 换向if (r < 0 || r >= m || c < 0 || c >= n || ans[r][c] != -1)d = (d + 1) % 4, r = i + dirs[d][0], c = j + dirs[d][1];i = r, j = c;}return ans;}
};

通用方法

可以看出熟悉套路之后I,II,IV都可以迎刃而解, 但是III需要考虑的多一些,

class Solution {
public:vector> spiralMatrix(int m, int n, ListNode* head) {// 方向数组: 右下左上int dirs[4][2]{{0, 1}, {1, 0}, {0, -1}, {-1, 0}};// 循环变量int r{}, c{}, d{}, i{}, j{};// 初始化结果数组vector ans(m * n);while (/* 满足循环条件 */) {// 更新结果ans[i][j] = kr = i + dirs[d][0], c = j + dirs[d][1];if (r < 0 || r >= m || c < 0 || c >= n || /* 元素被遍历过? */)// 换方向, 更新步d = (d + 1) % 4, r = i + dirs[d][0], c = j + dirs[d][1];// 更新索引i = r, j = c;}return ans;}
};

相关内容

热门资讯

离开旧爱,想坐慢车,看透彻了心... 离开旧爱,想坐慢车,看透彻了心就会是晴朗的 是哪首歌?分手快乐,梁静茹的一首老歌分手快乐 梁静茹 我...
火影忍者决斗场什么忍者能卡进墙... 火影忍者决斗场什么忍者能卡进墙里波风水门。1、利用瞬身术进竖核入墙内:首先选信尘择一个合适的墙壁,然...
只有再爱一次,才能忘记前男友吗... 只有再爱一次,才能忘记前男友吗?你可以多和你的好朋友谈心啊,多结交一些朋友一样可以让你淡忘他,不一定...
女的穿越时空回到古代朝鲜的言情... 女的穿越时空回到古代朝鲜的言情小说古灵的《替身》
求一部动漫,很久以前看的,忘记... 求一部动漫,很久以前看的,忘记了名字。是关于一个少女变身用扑克牌行窃的故事。圣少女(提醒:变身后穿黑...
好听的歌 劲爆的 伤感的 忧伤... 好听的歌 劲爆的 伤感的 忧伤的 都行求要听的 欢快 忧伤的都行 只要好听 分享下呗Gee-少...
汤圆创作里面容易签约嘛?难度怎... 汤圆创作里面容易签约嘛?难度怎么样?是特别好看的文文才会成功嘛?什么地方,没听说过。
异界小说 男主被冰封了 然后有... 异界小说 男主被冰封了 然后有一帮来拍电影的女的在洗澡的时候发现了他! 好像是这样的就记得这些还有点...
选择词语填在横线上(快来帮帮我... 选择词语填在横线上(快来帮帮我吧)调整 整顿 矗立 伫立1、调整 整顿2、耸立 伫立调整 整顿矗立...
朴灿烈香水百瑞德,灿烈用的是百... 朴灿烈香水百瑞德,灿烈用的是百瑞德哪种香味的香水?朴灿烈喜欢用的百瑞德香水是银色山泉这款,这款香水是...
精神分析的学习与自我成长的联系... 精神分析的学习与自我成长的联系?心理学专业人士来答卡伦 霍尼《神经症与人的成长》,如果你是专业的,你...
怎么就没一首我喜欢听的歌 怎么就没一首我喜欢听的歌你最喜欢听的歌,听久了也会腻。心情不要那么浮躁,就会找到你喜欢的那首歌
如果把地球直线挖通的话,人跳进... 如果把地球直线挖通的话,人跳进去会摔死还是会掉到另一端呢?应该会直接摔死,因为地球中心才是非常复杂的...
和男朋友分手,他居然说谢谢我给... 和男朋友分手,他居然说谢谢我给他上了一堂人生课,什么意思?虽然你们分手了,但是你们一起度过了一段人生...
带口哨的纯音乐 带口哨的纯音乐曲名:The Voyage艺人:The Mountaineering Club Orc...
禾葡兰的禾善基金的理念是什么? 禾葡兰的禾善基金的理念是什么?禾善基金是有什么理念呢?禾善基金是禾葡兰创办的互助基金会,基金会的救助...
名侦探柯南给工藤新一的挑战书每... 名侦探柯南给工藤新一的挑战书每集开头那段音乐,有完整的吗,不是剧场和动画那个!那首歌是仓木麻衣的《T...
路漫漫其修远兮的下一句 路漫漫其修远兮的下一句路漫漫其修远兮,吾将上下而求索”这句出自屈原的名作《离骚》。“路漫漫其修远兮,...
海伦凯勒的背景 海伦凯勒的背景 海伦·凯勒(Helen Keller)(1880年6月27日-1968年6月1日...
激情燃烧的岁月实际上就是中国人... 激情燃烧的岁月实际上就是中国人焕发出巨大的劳动热情2.咱们工人有力量的歌曲,焕发的是现代人的激情。以...