力扣54. 螺旋矩阵

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

前言

        跟着Carl哥学完了数组篇,螺旋矩阵不涉及什么算法,但是很考验对代码的掌控力和逻辑把握,跟着卡哥学完以后,自己手撕出来这道题太有成就感了。


正文

        根据题目可以模拟出顺时针画矩阵的过程:

                1、 上行从左到右

                2、 右列从上到下

                3、 下行从右到左

                4、 左列从下到上

        再到内部的矩阵,重复这个过程,所以一定要清楚每个过程的边界条件,是左开右闭,还是左闭右开。

        即:每一条边拐角的元素,在处理的时候每条边要保持一致。我坚持的是左闭右开原则。

        除此以外,1、我们还要清楚要转多少圈才能完整的走完外圈每个元素?

                          2、中间值怎么处理?

        比如:在一个3 * 4的矩阵,我们只需要一圈就能走完外圈的所有元素,在一个5 * 3的矩阵,我们同样只需要一圈就能走完外圈的所有元素,由此可见,需要转多少圈是由最短边来决定的。

       

              可见:当 行 > 列(宽 > 长)时,中间值是一个特殊的中间列;

                         当 列 > 行(长 > 宽)时,中间值是一个特殊的中间行;       

代码

        清楚以上几点,就可以手撕出螺旋矩阵的代码了,整体C++代码如下:

class Solution {
public:
    vector<int> spiralOrder(vector<vector<int>>& matrix) {
        int m = matrix.size(), n = matrix[0].size();       // 行, 列
        if(m == 0 || n == 0)    return {};
        vector<int> res(m * n);     // 一维数组存放结果
        int startx = 0, starty = 0; // 每圈的起始位置
        int offset = 1;             // 每圈循环, 每条边的长度
        int loop = min(m, n) / 2;   // 外圈圈数
        int mid = min(m, n) / 2;    // 中间值
        int count = 0;      
        int i, j;
        while(loop--){
            i = startx;
            j = starty;
            // 按左闭右开原则转圈
            for(; j < n - offset; j++)            // 上行从左到右
                res[count++] = matrix[startx][j];
            for(; i < m - offset; i++)            // 右行从上到下
                res[count++] = matrix[i][j];
            for(; j > starty; j--)                // 下行从右到左
                res[count++] = matrix[i][j];
            for(; i > startx; i--)                // 左行从下到上
                res[count++] = matrix[i][starty];
            startx++; 
            starty++;   // 起始位置+1,第一圈起始位置[0][0],第二圈起始位置[1][1]....
            offset++;   // 每圈每一条边遍历长度
        }
        // 中间值的情况,注:此处不能用mid % 2,当行列均为1时,mid % 2 = 0
        if(min(m, n) % 2){
            if(m > n){  // 宽大于长,中间还剩下一列没有遍历
                for(i = mid; i < mid + m - n + 1; i++)
                    res[count++] = matrix[i][mid];
            }
            else{       // 长大于宽,中间还剩下一行没有遍历
                for(i = mid; i < mid + n - m + 1; i++){
                    res[count++] = matrix[mid][i];
                }
            }
        }
        return res;
    }
};


总结

        在边界条件多的循环中,一定要先规定好一个原则,然后每次循环都按照这个原则走,才不会越写越乱,如果不按照固定规则来遍历,那就是一进循环深似海。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值