【一刷《剑指Offer》】面试题 20:顺时针打印矩阵

力扣对应题目链接:54. 螺旋矩阵 - 力扣(LeetCode)

牛客对应题目链接:顺时针打印矩阵_牛客题霸_牛客网 (nowcoder.com)


一、《剑指 Offer》内容


二、分析题目

写法二解法:

可以将矩阵看成若干层,首先输出最外层的元素,其次输出次外层的元素,直到输出最内层的元素。

定义矩阵的第 k 层是到最近边界距离为 k 的所有顶点。

对于每层,从左上方开始以顺时针的顺序遍历所有元素。假设当前层的左上角位于 (top, left),右下角位于 (bottom, right),按照如下顺序遍历当前层的元素:

  1. 从左到右遍历上侧元素,依次为 (top, left) 到 (top, right)。
  2. 从上到下遍历右侧元素,依次为 (top+1, right) 到 (bottom, right)。
  3. 如果 left < right 且 top < bottom,则从右到左遍历下侧元素,依次为 (bottom, right−1) 到 (bottom, left+1),以及从下到上遍历左侧元素,依次为 (bottom,left) 到 (top+1,left)。

遍历完当前层的元素之后,将 left 和 top 分别增加 1,将 right 和 bottom 分别减少 1,进入下一层继续遍历,直到遍历完所有元素为止。


三、代码

1、写法一

//力扣
class Solution {
private:
    vector<int> res;
public:
    void printCircle(vector<vector<int>>& matrix, int n, int m, int st)
    {
        int endX=n-1-st, endY=m-1-st;
        //左->右
        for(int j=st; j<=endY; j++)
            res.push_back(matrix[st][j]);
        //上->下
        if(st<endX)
            for(int i=st+1; i<=endX; i++)
                res.push_back(matrix[i][endY]);
        //右->左
        if(st<endX && st<endY)
            for(int j=endY-1; j>=st; j--)
                res.push_back(matrix[endX][j]);
        //下->上
        if(st<endY && st<endX-1)
            for(int i=endX-1; i>=st+1; i--)
                res.push_back(matrix[i][st]);
    }
    vector<int> spiralOrder(vector<vector<int>>& matrix) {
        //n行m列
        int n=matrix.size();
        if(n==0) return res;
        int m=matrix[0].size();
        int st=0;
        while(n>st*2 && m>st*2)
        {
            //一圈一圈打印
            printCircle(matrix, n, m, st);
            st++;
        }
        return res;
    }
};

//牛客
class Solution {
private:
    vector<int> res;
public:
    void printCircle(vector<vector<int>>& matrix, int n, int m, int st)
    {
        int endX=n-1-st, endY=m-1-st;
        //左->右
        for(int j=st; j<=endY; j++)
            res.push_back(matrix[st][j]);
        //上->下
        if(st<endX)
            for(int i=st+1; i<=endX; i++)
                res.push_back(matrix[i][endY]);
        //右->左
        if(st<endX && st<endY)
            for(int j=endY-1; j>=st; j--)
                res.push_back(matrix[endX][j]);
        //下->上
        if(st<endY && st<endX-1)
            for(int i=endX-1; i>=st+1; i--)
                res.push_back(matrix[i][st]);
    }
    vector<int> printMatrix(vector<vector<int> > matrix) {
        int n=matrix.size();
        if(n==0) return {};
        int m=matrix[0].size();
        int st=0;
        while(n>st*2 && m>st*2)
        {
            //一圈一圈打印
            printCircle(matrix, n, m, st);
            st++;
        }
        return res;
    }
};

2、写法二

//力扣
class Solution {
private:
    vector<int> res;
public:
    vector<int> spiralOrder(vector<vector<int>>& matrix) {
        int n=matrix.size();
        if(n==0) return res;
        int m=matrix[0].size();
        int left=0, right=m-1;
        int top=0, bottom=n-1;
        while(left<=right && top<=bottom)
        {
            for(int j=left; j<=right; j++)
                res.push_back(matrix[top][j]);
            for(int i=top+1; i<=bottom; i++)
                res.push_back(matrix[i][right]);
            if(left<right && top<bottom)
            {
                for(int j=right-1; j>=left; j--)
                    res.push_back(matrix[bottom][j]);
                for(int i=bottom-1; i>top; i--)
                    res.push_back(matrix[i][left]);
            }
            left++;
            right--;
            top++;
            bottom--;
        }
        return res;
    }
};
  • 4
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值