螺旋矩阵 - 中等

*************

C++

topic: 54. 螺旋矩阵 - 力扣(LeetCode)

*************

Look at the problem first.

Matrix is composed of n lines and n columns. Yesterday I learned how to creat one-dimension vector and two-dimension vector. And I am going to relearn again.

create one-dimension vector.

// 参数类型 参数名
vector<int> w;

// 直接传递参数
vector<int> w1 = {1, 2, 3, 4, 5};

// 构造参数
vector<int> w2(13, 38); // 13个元素,每个元素值为38

create two-dimension vector.

// 直接传递参数
vector<vector<int>> w3 = {{1, 2, 3}, {4, 5, 6}}; // 二维数组
// 构造参数
vector<vector<int>> w4(13, vector<int>(13, 38)); // 13行13列,每个元素值为38

Beside this, c++ allows you do something in vector library. Here are some basic usages I've meet in the topics.

// vector基础操作
vector<int> w(13, 0); 
// w = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; // 初始化为13个元素,每个元素值为0

// 末尾添加元素1
w.push_back(1); 
// w = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}; // 添加元素1

// 末尾添加元素2
w.push_back(2);
// w = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2}; // 添加元素2

// 末尾删除元素2
w.pop_back();
// w = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}; // 删除元素2

// 末尾删除元素1
w.pop_back();
// w = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; // 删除元素1

// 查看大小
int n = w.size();
// n = 13; // 大小为13

So need a coordinate axis system.

remember the last topic, matrix with directions? 

困于环中的机器人-优快云博客https://blog.youkuaiyun.com/ElseWhereR/article/details/146816399?spm=1001.2014.3001.5502

When looking at this topic, I tend to immediately refer the robot problem, which indicates the robot always turns right. Annotate that traverse the whole matrix is incrediblely crucial. So the return the reault and get the size is very cradible.

class Solution {
public:
    vector<int> spiralOrder(vector<vector<int>>& matrix) {
        
        // 初始化一个vector,用来存储遍历的数字
        vector<int> result;

        // 获得矩阵大小
        int m = matrix.size(); // 有多少行
        int n = matrix[0].size(); // 有多少列
    }
};

I have a doubt that why matrix[0].size() means the number of columns? and soon I figure out that matrix[0] means the first line of the matrix. and matrix[0].size() means the numbers of elements that the first line contains.

Deal with the first line is really easy.

class Solution {
public:
    vector<int> spiralOrder(vector<vector<int>>& matrix) {
        
        // 初始化一个vector,用来存储遍历的数字
        vector<int> result;

        // 获得矩阵大小
        int m = matrix.size(); // 有多少行
        int n = matrix[0].size(); // 有多少列

        for (int i = 0; i < m; i++)
        {
            result.push_back(matrix[0][i]);
        }
    }
};

and then turn right for the first time.

class Solution {
public:
    vector<int> spiralOrder(vector<vector<int>>& matrix) {
        
        // 初始化一个vector,用来存储遍历的数字
        vector<int> result;

        // 获得矩阵大小
        int m = matrix.size(); // 有多少行
        int n = matrix[0].size(); // 有多少列

        for (int i = 0; i < m; i++)
        {
            result.push_back(matrix[0][i]);
        }

        // 第一次向右转
        for (int j = 0; j < n; j++)
        {
            result.push_back(matrix[j][m - 1]);
        }
    }
};

and turn right for the second time.

class Solution {
public:
    vector<int> spiralOrder(vector<vector<int>>& matrix) {
        
        // 初始化一个vector,用来存储遍历的数字
        vector<int> result;

        // 获得矩阵大小
        int m = matrix.size(); // 有多少行
        int n = matrix[0].size(); // 有多少列

        for (int i = 0; i < m; i++)
        {
            result.push_back(matrix[0][i]);
        }

        // 第一次向右转
        for (int j = 0; j < n; j++)
        {
            result.push_back(matrix[j][m - 1]);
        }

        // 第二次程序转弯
        for (int i = n - 1; i >= 0; i--)
        {
            result.push_back(matrix[m - 1][i]);
        }
    }
};

You get it? Every three turnning around makes a loop. So define the top, bottom, left and right.

class Solution {
public:
    vector<int> spiralOrder(vector<vector<int>>& matrix) {
        
        // 初始化一个vector,用来存储遍历的数字
        vector<int> result;

        // 获得矩阵大小
        int m = matrix.size(); // 有多少行
        int n = matrix[0].size(); // 有多少列

        // 规定循环的边界感
        int top = 0;
        int bottom = m - 1;
        int left = 0;
        int right = n - 1;

        // 开始进入loop
        while (top <= bottom && left <= right)
        {
            // do somethig here
        }

    }
};

 

// 从左到右遍历上边界
            for (int j = left; j <= right; ++j) {
                result.push_back(matrix[top][j]);
            }
            top++;

// 从上到下遍历右边界
            for (int i = top; i <= bottom; ++i) {
                result.push_back(matrix[i][right]);
            }
            right--;

  // 从右到左遍历下边界
            for (int j = right; j >= left; --j) {
                result.push_back(matrix[bottom][j]);
            }
            bottom--;

 // 从下到上遍历左边界
            for (int i = bottom; i >= top; --i) {
                result.push_back(matrix[i][left]);
            }
            left++;

here we go:

class Solution {
public:
    vector<int> spiralOrder(vector<vector<int>>& matrix) {
        
        // 初始化一个vector,用来存储遍历的数字
        vector<int> result;

        // 获得矩阵大小
        int m = matrix.size(); // 有多少行
        int n = matrix[0].size(); // 有多少列

        // 规定循环的边界感
        int top = 0;
        int bottom = m - 1;
        int left = 0;
        int right = n - 1;

        // 开始进入loop
        while (top <= bottom && left <= right)
        {
            // do somethig here

            // →
            for (int j = left; j <= right; j++)
            {
                result.push_back(matrix[top][j]);
            }
            top++;

            // ↓
            for (int i = top; i <= bottom; ++i) 
            {
                result.push_back(matrix[i][right]);
            }
            right--;

            // ←
            for (int j = right; j >= left; --j) 
            {
                result.push_back(matrix[bottom][j]);
            }
            bottom--;

            // ↑
            for (int i = bottom; i >= top; --i) 
            {
                result.push_back(matrix[i][left]);
            }
            left++;

        }

        return result;
    }
};

The program seems perfecct and why is wrong?

0123
01234
15678
29101112

When the program go to matrix[1][2], which is 7, 6 is redundent.

  • 在第二轮循环开始时,top=1,bottom=1,left=1,right=2。进入循环。
  • 向右:j从1到2,添加matrix[1][1]=6,matrix[1][2]=7 → result变为[1,2,3,4,8,12,11,10,9,5,6,7]。然后top++到2。
  • 向下:i从2到bottom=1 → 不执行,直接跳过。right减到1。
  • 向左:j从1到left=1 → j=1,添加matrix[bottom=1][1]=6 → result变为[…,6,7,6]。然后bottom–到0.
  • 向上:i从0到top=2 → 循环条件i >=2,不执行。left++到2.
  • 此时,top=2,bottom=0 → 条件top<=bottom不成立,退出循环。

things goes wrong.

add if (top > bottom) break;  if (left > right) break;

class Solution {
public:
    vector<int> spiralOrder(vector<vector<int>>& matrix) {
        
        // 初始化一个vector,用来存储遍历的数字
        vector<int> result;

        // 获得矩阵大小
        int m = matrix.size(); // 有多少行
        int n = matrix[0].size(); // 有多少列

        // 规定循环的边界感
        int top = 0;
        int bottom = m - 1;
        int left = 0;
        int right = n - 1;

        // 开始进入loop
        while (top <= bottom && left <= right)
        {
            // do somethig here

            // →
            for (int j = left; j <= right; j++)
            {
                result.push_back(matrix[top][j]);
            }
            top++;

            // ↓
            for (int i = top; i <= bottom; ++i) 
            {
                result.push_back(matrix[i][right]);
            }
            right--;

            if (top > bottom)
            {
                break;
            }

            // ←
            for (int j = right; j >= left; --j) 
            {
                result.push_back(matrix[bottom][j]);
            }
            bottom--;

            if (left > right)
            {
                break;
            }

            // ↑
            for (int i = bottom; i >= top; --i) 
            {
                result.push_back(matrix[i][left]);
            }
            left++;

        }

        return result;
    }
};

# 力扣hot100刷题记录表 ### 一,哈希部分 - [ ] 1. 两数之和 (简单) - [ ] 2. 字母异位词分组(中等- [ ] 3. 最长连续序列(中等) ### 二,双指针部分 - [ ] 4. 移动零(简单) - [ ] 5. 盛水最多的容器 (中等- [ ] 6. 三数之和 (中等- [ ] 7. 接雨水(困难) ### 三,滑动窗口 - [ ] 8. 无重复字符的最长子串(中等- [ ] 9. 找到字符中所有的字母异位词(中等) ### 四,子串 - [ ] 10. 和为k的子数组(中等- [ ] 11. 滑动窗口最大值(困难) - [ ] 12. 最小覆盖子窜(困难) ### 五,普通数组 - [ ] 13. 最大子数组和(中等- [ ] 14. 合并区间(中等- [ ] 15. 轮转数组(中等- [ ] 16. 除自身以外数组的乘积(中等- [ ] 17. 缺失的第一个正数(困难) ### 六,矩阵 - [ ] 18. 矩阵置零(中等- [ ] 19. 螺旋矩阵 (中等) - [ ] 20. 旋转图像 (中等- [ ] 21. 搜索二维矩阵Ⅱ (中等) ### 七,链表 - [ ] 22. 相交链表 (简单) - [ ] 23. 反转链表 (简单) - [ ] 24. 回文链表 (简单) - [ ] 25. 环形链表 (简单) - [ ] 26. 环形链表Ⅱ (中等) - [ ] 27. 合并两个有序链表 (简单) - [ ] 28. 两数相加 (中等) - [ ] 29. 删除链表的倒数第 N 个结点 (中等) - [ ] 30. 两两交换链表中的节点 (中等) - [ ] 31. K个一组翻转链表 (困难) - [ ] 32. 随机链表的复制 (中等) - [ ] 33. 排序链表 (中等) - [ ] 34. 合并 K 个升序链表 (困难) - [ ] 35. LRU 缓存 (中等) ### 八,二叉树 - [ ] 36. 二叉树的中序遍历 (简单) - [ ] 37. 二叉树的最大深度 (简单) - [ ] 38. 翻转二叉树 (简单) - [ ] 39. 对称二叉树 (简单) - [ ] 40. 二叉树的直径 (简单) - [ ] 41. 二叉树的层序遍历 (中等) - [ ] 42. 将有序数组转换为二叉搜索树 (简单) - [ ] 43. 验证二叉搜索树 (中等) - [ ] 44. 二叉搜索树中第 K 小的元素 (中等) - [ ] 45. 二叉树的右视图 (中等) - [ ] 46. 二叉树展开为链表 (中等) - [ ] 47. 从前序与中序遍历序列构造二叉树 (中等) - [ ] 48. 路径总和 III (中等) - [ ] 49. 二叉树的最近公共祖先 (中等) - [ ] 50. 二叉树中的最大路径和 (困难) ### 九,图论 - [ ] 51. 岛屿数量 (中等) - [ ] 52. 腐烂的橘子 (中等) - [ ] 53. 课程表 (中等) - [ ] 54. 实现 Trie(前缀树) (中等) ### 十,回溯 - [ ] 55.全排列(中等) - [ ] 56.子集(中等) - [ ] 57.电话号码的字母组合(中等) - [ ] 58.组合总和(中等) - [ ] 59.括号生成(中等) - [ ] 60.单词搜索(中等) - [ ] 61.分割回文串(中等) - [ ] 62.N 皇后 (困难) ### 十一,二分查找 - [ ] 63. 搜索插入位置 (简单) - [ ] 64. 搜索二维矩阵 (中等) - [ ] 65. 在排序数组中查找元素的第一个和最后一个位置 (中等) - [ ] 66. 搜索旋转排序数组 (中等) - [ ] 67. 寻找旋转排序数组中的最小值 (中等) - [ ] 68. 寻找两个正序数组的中位数 (困难) ### 十二,栈 - [ ] 69. 有效的括号 (简单) - [ ] 70. 最小栈 (中等) - [ ] 71. 字符串解码 (中等) - [ ] 72. 每日温度 (中等) - [ ] 73. 柱状图中最大的矩形 (困难) ### 十三,堆 - [ ] 74. 数组中的第K个最大元素 (中等) - [ ] 75. 前K 个高频元素 (中等) - [ ] 76. 数据流的中位数 (闲难) ### 十四,贪心算法 - [ ] 77. 买卖股票的最佳时机 (简单) - [ ] 78. 跳跃游戏 (中等) - [ ] 79. 跳跃游戏 III (中等) - [ ] 80. 划分字母区间 (中等) ### 十五,动态规划 - [ ] 81. 爬楼梯(简单) - [ ] 82. 杨辉三角 (简单) - [ ] 83. 打家劫舍 (中等) - [ ] 84. 完全平方数 (中等) - [ ] 85. 零钱兑换 (中等) - [ ] 86. 单词拆分 (中等) - [ ] 87. 最长递增子序列 (中等) - [ ] 88. 乘积最大子数组 (中等) ### 十六,多维动态规划 - [ ] 91. 不同路径 (中等) - [ ] 92. 最小路径和 (中等) - [ ] 93. 最长回文子串 (中等) - [ ] 94. 最长公共子序列 (中等) - [ ] 95. 编辑距离 (中等) ### 十七,技巧 - [ ] 96. 只出现一次的数字 (简单) - [ ] 97. 多数元素 (简单) - [ ] 98. 颜色分类 (中等) - [ ] 99. 下一个排列 (中等) - [ ] 100. 寻找重复数 (中等) 如何使用
07-20
为了高效地使用 LeetCode Hot 100 题目列表进行刷题和提升算法能力,可以采取以下几个策略: ### 1. 制定合理的刷题计划 设定一个每日或每周的刷题目标,例如每天解决 2-3 道题目。这样可以避免过度压力,同时保持持续的进步。优先选择与自己当前技能水平匹配的题目,逐步挑战更高难度的问题。 ### 2. 深入理解每道题目 不要仅仅满足于通过题目,而是要深入理解解题思路和背后的算法原理。例如,在解决类似单词拆分(Word Break)问题时,可以使用动态规划的方法,将问题分解为子问题进行求解[^2]。代码示例如下: ```python def wordBreak(s, wordDict): word_set = set(wordDict) n = len(s) dp = [False] * (n + 1) dp[0] = True # 空字符串可以被拆分 for i in range(1, n + 1): for j in range(i): if dp[j] and s[j:i] in word_set: dp[i] = True break return dp[n] ``` ### 3. 多种方法解决问题 尝试使用不同的方法解决同一道题目,例如递归、动态规划、贪心算法等。这有助于提高解决问题的灵活性和深度理解不同算法的适用场景。例如,在解决汉诺塔问题时,可以通过递归思想实现[^3]。 ### 4. 复盘与总结 每次完成一道题目后,花时间总结解题思路和技巧。记录下自己的学习笔记,例如常见的算法模板、易错点以及优化思路。这有助于形成系统的知识体系。 ### 5. 结合官方题解和其他资源 参考 LeetCode 官方题解和其他高质量的学习资源,了解最优解和不同解法的时间复杂度分析。这可以拓宽思路,帮助找到更高效的解决方案。 ### 6. 参与讨论与分享 加入 LeetCode 讨论区或相关学习社区,与其他刷题者交流解题思路。分享自己的解法并学习他人的经验,可以快速提升自己的算法水平。 ### 7. 使用分类刷题法 LeetCode Hot 100 题目涵盖多个算法类别,如数组、字符串、动态规划、树等。按类别集中刷题有助于系统性地掌握某一类问题的解法。例如,先集中解决所有与动态规划相关的题目,再转向其他类别。 ###
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值