顺时针打印矩阵

题目描述

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

这个题有两种方法,剑指offer里使用的是第一种方法,即每次打印一圈,第i圈从位置(i,i)开始打印,但是这种方法只适用于方阵,或者列数大于行数的矩阵。对于只包含一列的矩阵会有错误。

第二种方法是,转圈法,设置4个标志位表示四个方向,用int[][] book访问矩阵来表示对应的位是否已经访问,这种方法的空间复杂度为O(m*n),如果还有其他方法,也可以在给出提示,不胜感激。

方法一

    //顺时针打印矩阵
    public ArrayList<Integer> printMatrix(int [][] matrix) {

        if(matrix==null || matrix.length<=0 || matrix[0].length<=0){
            return null;
        }
        ArrayList<Integer> res = new ArrayList<Integer>();

        // 1.计算需要打印多少次,即打印多少个圈
        int printRow = (matrix.length+1)/2;//注意在计算打印次数是加1,这样在1行时,打印一次,在4行时打印两次,在5行时打印三次
        int row = matrix.length,col = matrix[0].length;


        for(int i=0;i<printRow;i++){    //第i次,从(i,i)开始打印
            printCircle(matrix,res,i,row,col);
        }

        return res;
    }

    //打印第i圈
    public void printCircle(int[][] matrix,ArrayList<Integer> res,int i,int row,int col){
        int right = col-1-i;
        int down = row-1-i;

        //->
        for(int left = i;left<=right;left++){
            res.add(matrix[i][left]);
        }

        //up down,记住这一行的最后一个已经被打印了,从下一行开始打印
        for(int up=i+1;up<=down;up++){
            res.add(matrix[up][right]);
        }

        //最后一列的最后一个已经被打印了,从次最后列开始打印
        for(int r=right-1;r>=i;r--){
            res.add(matrix[down][r]);
        }

        for(int b=down-1;b>i;b--){
            res.add(matrix[b][i]);
        }
    }

方法二:

//顺时针打印矩阵
    public ArrayList<Integer> printMatrix(int [][] matrix) {

        ArrayList<Integer> res = new ArrayList<Integer>();

        if(matrix.length==0 || matrix[0].length==0){
            return res;
        }
        int width = matrix[0].length;
        int high = matrix.length;


        //top,down,left,right;
        //四个方向分别用1,2,3,4来表示
        int direct = 4;
        boolean[][] book = new boolean[high][width];
        int i=0,j=-1;

        while(true){

            //四个方向都访问完毕
            if((j+1<width&&book[i][j+1]||j+1==width)    //右
                    && (i+1<high&&book[i+1][j]||i+1==high)  //下
                    && (i-1>=0&&book[i-1][j]||i-1==-1)  //上
                    && (j-1>=0&&book[i][j-1]||j-1==-1)){//左
                break;
            }

            //根据方向来进行遍历
            switch (direct){
                case 4:
                    while(j+1<width&&!book[i][j+1]){
                        book[i][j+1] = true;
                        res.add(matrix[i][j+1]);
                        j++;
                    }
                    direct = 2;
                    break;
                case 2:
                    while(i+1<high&&!book[i+1][j]){
                        book[i+1][j] = true;
                        res.add(matrix[i+1][j]);
                        i++;
                    }
                    direct = 3;
                    break;
                case 3:
                    while(j-1>=0&&!book[i][j-1]){
                        book[i][j-1] = true;
                        res.add(matrix[i][j-1]);
                        j--;
                    }
                    direct = 1;
                    break;
                case 1:
                    while(i-1>=0&&!book[i-1][j]){
                        book[i-1][j] = true;
                        res.add(matrix[i-1][j]);
                        i--;
                    }
                    direct = 4;
            }

        }

        return res;
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值