剑指offer- 顺时针打印矩阵 精品算法

剑指offer 刷了这么多题但是这一道,这个算法和其他人的算法都不一样 ,必须吹爆,

题目描述:

输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字,例如,如果输入如下4 X 4矩阵: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 则依次打印出数字1,2,3,4,8,12,16,15,14,13,9,5,6,7,11,10.

解题思路

把题目给出的矩阵看成一个二维平面, 顺时针打印 就是顺时针走过二维平面,从轨迹上来看可以知道,当走到边界时,对走方向进行判断(优先级为上 ,右 ,下 ,左 ,即能上就不上 , 不上就右),上 ,右不通 , 左走过 , 只能下 ,就向下走
在这里插入图片描述
当下走到底时,同理,只能向左 ,
在这里插入图片描述
然后问题就出现在向做一步走的时候 , 走了一步后,由于优先级是先上,此时就会向上走,导致样例不通过。
在这里插入图片描述
所以使用last 变量 来记录 上一次的方向 , 且上一次方向优先级最高 。

代码实现

class Solution {
public:
    vector<int> printMatrix(vector<vector<int> > matrix) {
       //最直观的做法就是按照题目要求,遍历矩阵的边界,首先我们可以看出遍历到边界的时候,是向右遍历。
        //
        vector<int>res;
        int row = 0 , col = 0;
        const int mt_row = matrix.size();
        const int mt_col = matrix[0].size();
        int last = 10; //存储上次的方向 第一次就是右边
        int ** mt = (int **)malloc(sizeof(int*)*mt_row);  //记录路程
        for(int i = 0 ; i < mt_row ; i++){
            *(mt+i) = (int *)malloc(sizeof(int)*mt_col);
            memset(*(mt+i),0,sizeof(int)*mt_col);
        }
        res.push_back(matrix[row][col]);
        mt[row][col] = 1;
        while(direct(mt,row ,col,mt_row,mt_col,last)!=0){
                res.push_back(matrix[row][col]);
        }
        return res;
    }
    int direct(int ** mt,int & row ,int & col,const int mt_row , int mt_col ,int & last) // 0 表示结束 (0,1) 1 表示下 ,(0,-1)-1 表示上 ,(1,0) 10 表示右边 , (-1,0)-10 表示左边
    {   
        switch (last){
            case 1:
                if(row +1 < mt_row && mt[row+1][col]!=1) //向下延展
                {
                    mt[++row][col] = 1;
                    return 1;
                }
                break;
            case -1:
                if(row-1>=0 && mt[row-1][col] != 1) //向上延展
                {
                    mt[--row][col] = 1;
                    return -1;
                }
                break;
            case 10:
                if(col + 1< mt_col && mt[row][col+1]!=1) //向右延展
                {
                    mt[row][++col] = 1;
                    return 10;
                }
                break;
            case -10:
                if(col -1 >= 0 && mt[row][col-1] != 1) //向左延展
                {
                    mt[row][--col] = 1;
                    return -10;
                }
                break;
        }
        //顺序即为优先级
        if(row-1>=0 && mt[row-1][col] != 1) //向上延展
        {
            mt[--row][col] = 1;
            last = -1;
            return -1;
        }
        if(col + 1< mt_col && mt[row][col+1]!=1) //向右延展
        {
            mt[row][++col] = 1;
            last = 10;
            return 10;
        }
        if(row +1 < mt_row && mt[row+1][col]!=1) //向下延展
        {
            mt[++row][col] = 1;
            last = 1;
            return 1;
        }
        if(col -1 >= 0 && mt[row][col-1] != 1) //向左延展
        {
            mt[row][--col] = 1;
            last = -10;
            return -10;
        }
         
        return 0;
    }
};

引申

这个代码不仅能实现顺时针, 同样还可以逆时针,甚至X型 S型 都可以实现,前两者只需要对direct 函数进行优先级的调整 ,后者需要增加新的方向。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值