数据结构-剑指offer-顺时针打印矩阵

题目:输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字。

1、思路1:可以将上下左右四个范围设定,通过改变上下左右四个界限,实现顺时针打印。


class Solution {
public:
    vector<int> printMatrix(vector<vector<int> > matrix) {
        //行数row
        int row = matrix.size();
        //列数col
        int col = matrix[0].size();
        vector<int> res;
        if(row == 0 && col == 0)
            return res;
        //初始元素的行为0
        int leftTop = 0;
        //右上角的元素的列
        int rightTop = col - 1;
        //初始元素的列为0
        int leftBottom = 0;
        //右下角的元素的行
        int rightBottom = row - 1;
        while(leftTop<=rightTop && leftBottom<=rightBottom)
        {
            for(int i=leftTop; i <= rightTop; i++)
                res.push_back(matrix[leftTop][i]);
            for(int i = leftTop + 1; i <= rightBottom; i++)
                res.push_back(matrix[i][rightTop]);
            //如果leftTop=rightBottom,就不需要执行下面的步骤了            
            if(leftTop != rightBottom)
            for(int i = rightTop-1;i >= leftTop;i --)
                res.push_back(matrix[rightBottom][i]);
            if(rightTop != leftBottom)
            for(int i = rightBottom-1; i > leftTop; i--)
                res.push_back(matrix[i][leftBottom]);
            leftTop++;   leftBottom++;
            rightTop--;  rightBottom--;
        }
        return res;
    }
};

2、书上的思路:左上角的左上角的左边中行标和列标总是相同的,于是可以在矩阵中选取左上角为(start,end)的一圈作为分析目标。其循环继续的条件是columns>startX×2并且rows>startY×2.

运行出现错误:


class Solution {
public:
    void printMatrix(int** matrix,int columns,int rows) {
        //int columns = matrix[0].size();
        //int rows = matrix.size();
        if(matrix == nullptr || columns<=0 || rows<=0)
            return;
        int start = 0;
        while(columns>start*2 && rows>start*2){
            PrintMatrixInCircle(matrix,columns,rows,start);
            start++;
        }
    }
    void PrintMatrixInCircle(int** matrix,int columns,int rows,int start){
        int endX=columns-1-start;
        int endY=rows-1-start;
        //从左到右打印
        for(int i=start;i<=endY;i++){
            int number = matrix[start][i];
            printNumber(number);
        }
        //从上到下打印
        if(start<endY){
            for(int i=start+1;i<=endX;i++){
                int number = matrix[i][endX];
                printNumber(number);
            }
        }
        //从右到左打印
        if(start<endX&&start<endY){
            for(int i=endX-1;i>=start;i--){
                int number = matrix[endY][i];
                printNumber(number);
                
            }
        }
        //从下到上打印
        if(start<endX&&start<endY-1){
            for(int i=endY-1;i>start;i--){
                int number = matrix[i][start];
                printNumber(number);
            }
        }
    }
    void printNumber(int number)
    {
        printf("%d\t", number);
    }
};

3、将二者结合:因为每一次循环开始左上角的坐标中行标和列标总是相等,所以令leftTop=leftBottom=start=0;rightTop=endY=col-1-start; rightBottom=endX=row-1-start;

class Solution {
public:
    vector<int> printMatrix(vector<vector<int> > matrix) {
        //行数row
        int row = matrix.size();
        //列数col
        int col = matrix[0].size();
        vector<int> res;
        if(row == 0 && col == 0)
            return res;
        //初始元素行标和列标相同均为0
        int start = 0;
        while(col>start*2 && row>start*2){
            //右上角的元素的列
            int endY = col - 1 -start;
            //初始元素的列为0
            int endX = row - 1 -start;
            //从左到右打印
            for(int i=start; i <= endY; i++)
                res.push_back(matrix[start][i]);
            //从上到下打印,第二步的前提条件是:终止行数大于起始行数
            if(start<endX){
                for(int i = start + 1; i <= endX; i++)
                    res.push_back(matrix[i][endY]);}
            //第三步打印的前提条件是圈内至少两行两列,所以要求终止行数大于起始行数,终止列数大于起始列数
            if(start <endX && start<endY){
                for(int i = endY-1;i >= start;i--)
                    res.push_back(matrix[endX][i]);}
            //需要第四步的条件是三行两列(两行两列就不需要了,第三步已经打印完成了),所以终止行号比起始行号至少大2,终止列号大于起始列号
            if(start<endY && start<endX-1){
                for(int i = endX-1; i > start; i--)
                    res.push_back(matrix[i][start]);}
            start++;
        }
        return res;
    }
};


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值