顺时针打印矩阵

题目:

输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字,例如,如果输入如下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.

方法一:

用四个数分别表示第一行,最后一行,第一列,最后一列,旋转依次打印第一行,最后一列,最后一行,第一列,一次旋转打印结束后,丢弃最外面一层,行列分别前进后退。

!!!注意:为防止出现单行、单列而导致有些元素打印两次的问题,需要加入条件判断,使单行时,行打印一遍;单列时,列打印一遍。

class Solution {
public:
    vector<int> printMatrix(vector<vector<int> > matrix) 
    {
        int row=matrix.size();
        int col=matrix[0].size();
        vector<int>result;
        if(row==0||col==0)
            return result;
        int lef=0,rig=col-1,top=0,bot=row-1;        // 定义四个关键变量,表示左上和右下的打印范围
        while((lef<=rig)&&(top<=bot))
        {
            for(int i=lef;i<=rig;i++)
                result.push_back(matrix[top][i]);
            for(int i=top+1;i<=bot;i++)
                result.push_back(matrix[i][rig]);
            if(bot>top)                             //防止单行时,行打印两遍
            {
                for(int i=rig-1;i>=lef;i--)
                result.push_back(matrix[bot][i]);
            }

            if(rig>lef)                             //防止单列时,列打印两遍
            {
                for(int i=bot-1;i>=top+1;i--)
                result.push_back(matrix[i][lef]);
            }

            lef++;rig--;top++;bot--;
        }
        return result;
    }
};

方法二:

一个循环就能搞定:
1.先横向正走,再纵向正走,再横向反走,再纵向反走,再横向正走。。。循环往复。
2.横向走完后,纵向走的最大距离减一,纵向走完后,横向的最大距离减一。
3.横向走的初始距离为矩阵的宽度,纵向走的初始距离为矩阵的高度减一(其实是因为2的原因减一)。
为保持初始的横向正走的距离为矩阵宽度,初始的下标设为0,-1。然后就可以发车了。

class Solution {
public:
    vector<int> printMatrix(vector<vector<int> > matrix) 
    {
        int l=matrix[0].size();             //车在当前这一行能走的最大距离
        int w=matrix.size();                //车在当前这一列能走的最大距离
        int posx=-1;                        //车的当前所处的列坐标,初始化为-1,这样+矩阵宽度刚好到边界
        int posy=0;                         //车当前所处的行坐标。  
        int pathx=1;                        //车在当前这一行所走的距离,不能大于l。等于0则纵向走。
        int pathy=0;                        //车在当前这一列所走的距离,不能大于w。等于0则横走。
        int flag=1;                         //车的反向转弯标志。
        vector<int> vec;

        while(l > 0 && w > 0)               //当横向纵向一个无路可走,就退出循环
        {
            vec.push_back(matrix[posy+pathy][posx+pathx]);//把车当前位置的数据存入
            if(pathx != 0)                                //pathx !=0 代表目前正在横向走
            {
                if( abs(pathx + flag) <= l)               //判断是不是撞墙了,压线了
                    pathx=pathx+flag;                     //注意flag,因为会反向。事实上,每次纵向走完就反向
                else
                {
                    pathx=0;                              //横向不走了
                    pathy=flag;                           //让纵向开始走(flag不变是因为横向走完不会反向)
                    posx=posx+flag*l;                     //更新纵向走的初始位置
                    w--;                                  //纵向能走的距离减一,因为这一行走完,少了一列。
                }
            }

            else if(pathy != 0)                           //横向走完,pathx设0,pathy设为1或-1,可以走了
            {
                if( abs(pathy +flag) <= w )
                    pathy=pathy+flag;
                else
                {
                    pathy=0;
                    posy=posy+flag*w;
                    flag=flag*(-1);                    //上面和横向一样,这里要注意,以为每次纵向走完,要反向
                    pathx=flag;
                    l--;
                }
            }
        }
        return vec;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值