折磨:螺旋升天矩阵总结

本文将持续更新

零、前言

螺旋矩阵遍历,其实本身是一个描述类问题,本来不想总结,但由于lc把它标为简单题,导致人在极度愤怒的情况下做不明白。故想总结一下。

在处理描述性问题的时候,一定要找规律尤其是不变的方法。

一、正方形螺旋矩阵

59. 螺旋矩阵 II

1.思路

  • 层层扒皮,层层遍历
  • 遍历方式:每一行(列)遍历n-1个元素(n为一行中的元素个数)
  • 处理结束时的情况:可能是一个元素,可能是一列或者一行元素。此时我们无法向以上那样扒皮遍历了。正方形最终结束的方式只能是下图中的方式,或者中间有一个元素的方式。而下图中的方式是符合我们的扒皮规则的,因此只需要将最后只有一个的方式单独拎出来就好。

2.实现

class Solution {
public:
    vector> generateMatrix(int n) {
        vector> arr;
        arr.resize(n);
        for(int i=0;i<n;i++)
        {
            arr[i].resize(n);
        }
        int m=arr[0].size();
        int i=0;
        int j=0;
        int count=1;
        while(i<=((m+1)/2-1))//(i,i)为一圈的起始位置
        {
            int d=n-i*2;//d表示这一圈有几个元素
            if(d==1)
            {
                arr[i][i]=count;
            }
            int a=i;
            int b=i;
            while(b<i+d-1)
            {
                arr[a][b]=count;
                count++;
                b++;
            }
            while(a<i+d-1)
            {
                arr[a][b]=count;
                count++;
                a++;
            }
            while(b>i)
            {
                arr[a][b]=count;
                count++;
                b--;
            }
            while(a>i)
            {
                arr[a][b]=count;
                count++;
                a--;
            }
            i++;
        }
        return arr;
    }
};

二、矩形矩阵

54. 螺旋矩阵

这个玩意真的折磨,题主在做的时候没有考虑周全矩阵的结束形状,导致花费了好多时间:

1.思路

1.只需要遍历的时候将正方形的边使用矩形的两边来表示。

2.当结束的时候,行或者列有一个为1,此时符合,需要特殊情况处理,类似正方形中只有一个元素。我的处理方式是直接使用两个for循环来加载所有元素。

2.实现

class Solution {
public:
    vector spiralOrder(vector>& matrix) {
        vector arr;
        arr.resize(matrix.size()*matrix[0].size());
        int a=0;//行下标
        int b=0;//列下标
        int i=0;//每一层起始位置
        int d=0;//每一圈有几个元素
        int count=0;//数组下标
        int Row=matrix.size();
        int Col=matrix[0].size();
        int size=Row<Col?Row:Col;
        int row=0;//每小圈的行
        int col=0;//每小圈的列
        while(i<=(size+1)/2-1)//计算循环几圈
        {
            row=Row-2*i;
            col=Col-2*i; 
            a=i;
            b=i;
            if(row==1||col==1)
            {
                for(int m=a;m<row+a;m++)
                {
                    for(int n=b;n<col+b;n++)
                    {
                        arr[count++]=matrix[m][n];
                    }
                }
                return arr;
            }
            while(b<i+col-1)
            {
                arr[count]=matrix[a][b];
                count++;
                b++;
            }
            while(a<i+row-1)
            {
                arr[count]=matrix[a][b];
                count++;
                a++;
            }
            while(b>i)
            {   
                arr[count]=matrix[a][b];
                count++;
                b--;
            }
            while(a>i)
            {
                arr[count]=matrix[a][b];
                count++;
                a--;
            }
            i++;
        }
        return arr;
    }
};

但是这段代码在剑指offer中是通过不了的,时间超时,但是在这里可以通过。

在剑指offer中看到了这样一种写死循环的写法,通过对边界的判定来结束死循环。

class Solution {
public:
    vector spiralOrder(vector>& matrix) {
        if (matrix.size() == 0 || matrix[0].size() == 0) 
            return {};
        vector res;
        int top = 0;                      //上边界
        int bottom = matrix.size() - 1;   //下边界
        int left = 0;                     //左边界
        int right = matrix[0].size() - 1; //右边界       
        while (true) {
            // 从左到右
            for (int i = left; i <= right; ++ i) 
                res.push_back(matrix[top][i]);
            // 每次从左往右执行一次,则要往下移一层
            if (++ top > bottom) break;
            // 从上到下
            for (int i = top; i <= bottom; ++ i) 
                res.push_back(matrix[i][right]);
            // 每次从上到下执行一次,则要往左移一列
            if (-- right < left) break;
            // 从右到左
            for (int i = right; i >= left; -- i) 
                res.push_back(matrix[bottom][i]);
            // 每次从右到左执行一次,则要往上移一行
            if (-- bottom < top) break;
            // 从下到上
            for (int i = bottom; i >= top; -- i) 
                res.push_back(matrix[i][left]);
            // 每次从下到上执行一次,则要往右移一列
            if (++ left > right) break;
        }
        return res;
    }
};

三、总结

螺旋升天数组这类的描述型题目,非常考察统筹规划的能力,需要有一个明确清楚的思路再开始写代码,一般关键在于一层一层展开问题的时候找到那个统一的处理办法。

本文将持续更新

#算法#
全部评论

相关推荐

被普调的六边形战士很高大:项目经历貌似和专业或者求职方向没大关系?
点赞 评论 收藏
分享
04-18 15:58
已编辑
门头沟学院 设计
kaoyu:这一看就不是计算机的,怎么还有个排斥洗碗?
点赞 评论 收藏
分享
评论
点赞
1
分享

创作者周榜

更多
牛客网
牛客企业服务