zoukankan      html  css  js  c++  java
  • 29 顺时针打印矩阵(四-画图让抽象问题形象化)

    题目描述:

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

    例如,如果输入如下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.

    测试用例:

     矩阵中有多行多列、矩阵中只有一行或者一列、数组中只有一列、数组中只有一行一列。(并没有考虑矩阵为空的情况)

    解题思路:

    1)^-^- 规律:每次圈的起始点都是(0,0)(1,1)(start,start)行列的数字相等

          ^-^- 一个矩阵能划分为多少个圈:找规律

          对于一个5*5的矩阵,最后一圈只有一个数字,对应的坐标为(2,2)。5>2*2

          对于一个6*6的矩阵,最后一圈只有一个数字,对应的坐标为(2,2)。6>2*2

         于是可以得出。让循环继续的条件是 columns>startX*2 并且 rows>startY*2

         ^-^- 可以把打印一圈分为四步:第一步,从左到右打印一行;第二步,从上到下打印一列;第三步,从右到左打印一行;第四步,从下到上打印一列。每一步根据起始坐标和终止坐标用循环打印出一行或者一列。

          

    class Solution {
    public:
        vector<int> printMatrix(vector<vector<int> > matrix) {
            if(matrix.size()==0)  //
                return result;
            
            int start = 0; //标志着第几圈
            int rows = matrix.size();
            int cols = matrix[0].size();
            while(rows>start*2 && cols>start*2){
                printMatrixInCircle( matrix,rows,cols,start);
                start++;
            }
            return result;
        }
        
        void printMatrixInCircle(vector<vector<int> > matrix,int rows,int cols,int start){
            int endCol = cols-1-start;
            int endRow = rows-1-start;
            
            //第一步:打印第一行(一定会打印)
            for(int col=start; col<=endCol; col++){
                result.push_back(matrix[start][col]);
            }
            //第二步:若行数大于等于二(即多于一行时),则会打印。即endRow-start>0
            if(endRow-start>0){
                for(int row=start+1; row<=endRow; row++)
                    result.push_back(matrix[row][endCol]);
            }
            //第三步:至少两行两列
            if(endRow-start>0 && endCol-start>0){ //
                for(int col=endCol-1; col>=start; col--)
                    result.push_back(matrix[endRow][col]);
            }
            //第三步:至少三行两列
            if(endRow-start>1 && endCol-start>0){
                for(int row=endRow-1; row>start; row--)
                    result.push_back(matrix[row][start]);
            }
        }
    private:
        vector<int> result;
    };
    

    2)int circle=((row<collor?row:collor)-1)/2+1;//圈数

    3)定义四个关键变量,表示左上和右下的打印范围,限定一个圈。每次循环后缩小一圈

    /*
        思想,用左上和右下的坐标定位出一次要旋转打印的数据,一次旋转打印结束后,往对角分别前进和后退一个单位。
        提交代码时,主要的问题出在没有控制好后两个for循环,需要加入条件判断,防止出现单行或者单列的情况。
     */
    class Solution {
    public:
        vector<int> printMatrix(vector<vector<int> > matrix) {
            int row = matrix.size();
            int col = matrix[0].size();
            vector<int> res;
             
            // 输入的二维数组非法,返回空的数组
            if (row == 0 || col == 0)  return res;
             
            // 定义四个关键变量,表示左上和右下的打印范围
            int left = 0, top = 0, right = col - 1, bottom = row - 1;
            
            while (left <= right && top <= bottom) //至少有一个元素时
            {
                // left to right 一定会打印
                for (int i = left; i <= right; ++i)  res.push_back(matrix[top][i]);
                // top to bottom 行数多于1行才会打印  here 只有一行时不会进入for循环,因此该处无需判断
                for (int i = top + 1; i <= bottom; ++i)  res.push_back(matrix[i][right]);
                // right to left //至少两行两列时,才会打印 top != bottom限制至少两行 for循环限制right-1>=left,即至少两行
                if (top != bottom)
                    for (int i = right - 1; i >= left; --i)  res.push_back(matrix[bottom][i]);
                // bottom to top //至少三行两列  left != right限制两列 bottom - 1> top 至少三列
                if (left != right)
                    for (int i = bottom - 1; i > top; --i)  res.push_back(matrix[i][left]);
                
                left++,top++,right--,bottom--; //缩小一圈
            }
            return res;
        }
    };
    

    4)顺着走,即向右->向下->向左->向上,一共要走(长*宽)步。遇到边界就改变方向,当向上碰到顶的时候,四个边界都缩小。思路简单,一个循环即可!

    class Solution {
    public:
        vector<int> printMatrix(vector<vector<int> > matrix) {
            vector<int> ret;
            if(matrix.empty())return ret;
                 
            int x,y,cnt=matrix[0].size()*matrix.size(); //一共需要打印的个数
            //右rEdge 下dEdge 左lEdge 上uEdge
            int rEdge=matrix[0].size()-1,dEdge=matrix.size()-1,lEdge=0,uEdge=0;
            //bool first=true;
            for(x=0,y=0;cnt>0;cnt--){ //从(0,0)开始
                ret.push_back(matrix[x][y]);
                //go  right
                if(x==uEdge){  //上边界
                    if(y<rEdge) //小于右边界时,向右移动。y++
                        y++;
                    else if(y==rEdge) //到达右边界,向下移动
                        x++;
                    continue; //不会再判断后面的if了
                }
                 
                //down
                if(y==rEdge){
                    if(x<dEdge)
                        x++;
                    else if(x==dEdge){
                        y--;
                    }
                    continue; //不会再判断后面的if了
                }
                 
                //left
                if(x==dEdge){
                    if(y>lEdge)
                        y--;
                    else if(y==lEdge){
                        x--;
                    }
                    continue; //不会再判断后面的if了
                }
                 
                //up
                if(y==lEdge){
                    if(x>uEdge+1)
                        x--;
                    else if( x==uEdge+1){ //到达一圈的最后一个点
                        y++;
                        lEdge++;
                        uEdge++;
                        rEdge--;
                        dEdge--;
                    }
                    continue;
                }
                //;3
            }
            return ret;
        }
    };
    

      

      

      

  • 相关阅读:
    数据库相关
    linux相关
    类相关
    异常处理
    一些类的概念
    安装插件
    接口开发
    redis相关
    大数据-概览
    大数据-浅谈OLTP与OLAP
  • 原文地址:https://www.cnblogs.com/GuoXinxin/p/10449568.html
Copyright © 2011-2022 走看看