JAVA: 顺时针打印矩阵

题目:

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

5     6    7    8

9    10  11  12

13  14  15  16

方法一:

介绍一种矩阵处理方式:矩阵分圈处理。在矩阵中用左上角的坐标(tR,tC)和右下角的坐标(dR,dC)可以表示一个子矩阵,如题目中矩阵,当(tR,tC)=(0,0)、(dR,dC)=(3,3)时,表示的子矩阵就是整个矩阵,那么这个子矩阵的最外层的部分为:

1     2    3    4

5                8

9               12

13  14  15  16

把这个子矩阵的最外层顺时针打印出来,那么在(tR,tC)=(0,0)、(dR,dC)=(3,3)时,打印的结果为:1,2,3,4,8,12,16,15,14,13,9,5。接下来,分别使tR和tC加1,dR和dC减1,即(tR,tC)=(1,1)、(dR,dC)=(2,2)时,此时的子矩阵为:

 6     7    

10   11

再把这个矩阵顺时针打印出来,结果为6,7,11,10。再把tR和tC加1,dR和dC减1,即(tR,tC)=(2,2)、(dR,dC)=(1,1)。如果左上角坐标位于右下角坐标的右方或者下方(即tR>dR ||tC>dC),则停止,已经打印的所有结果即为要求的打印结果。

package Array;

import java.util.ArrayList;
import java.util.List;

public class spiralOrder {
    /**
     * @param matrix: a matrix of m x n elements
     * @return: an integer list
     */
    //转圈打印矩阵
    //左上角点(tR,tC),右下角(dR,dC)
    public List<Integer> spiralOrder(int[][] matrix) {
        // write your code here
        List<Integer>   list=new ArrayList<>();
        if(matrix==null||matrix.length==0)   return list;
        int dR=matrix.length-1;
        int dC=matrix[0].length-1;
        int tR=0;
        int tC=0;
        while(tR<=dR && tC<=dC ){
            PrintMatrix(matrix,list,tR++,tC++,dR--,dC--);
        }
        return list;
    }

    private void PrintMatrix(int[][] matrix,List<Integer> list,int tR,int tC,int dR,int dC){
        if(tR==dR){   // 子矩阵只有一行
            for(int i=tC;i<=dC;i++)
                list.add(matrix[tR][i]);
        }else if(tC==dC){  // 子矩阵只有一列
            for(int i=tR;i<=dR;i++)
                list.add(matrix[i][tC]);
        }else{
            int curC=tC;
            int curR=tR;
            while(curC!=dC){
                list.add(matrix[tR][curC]);
                curC++;
            }
            while(curR!=dR){
                list.add(matrix[curR][dC]);
                curR++;
            }
            while (curC!=tC){
                list.add(matrix[dR][curC]);
                curC--;
            }
            while(curR!=tR){
                list.add(matrix[curR][tC]);
                curR--;
            }
        }
    }

    public static void main(String[] args) {
        spiralOrder spiralOrder=new spiralOrder();
        int[][] matrix={};
        System.out.println(spiralOrder.spiralOrder(matrix));
    }
}

方法二:

分析:如果以矩阵左上角为(0,0),则每一圈开始的点是(0,0)、(1,1)...,可以观察如果2*2矩阵,只打印1圈,3*3矩阵,打印2圈,3*2矩阵,打印1圈,所以有col>count*2 && row>count*2,count从0开始。

对于每一圈的打印,开始的行号和列号都为count,结束的行号endrow=row-1-count,结束的列号endcol=col-1-count。

第一步从左向右打印是必须的,循环打印,行号为count,列号为count到endrow递增。

第二步从上往下打印满足的条件是终止行号大于开始行号endrow>count,循环打印,行号为count+1到endrow递增,列号为endcol。

第三步从右往左打印满足的条件是第二步条件终止行号大于开始行号endrow>count并且终止列号大于开始列号endcol>count,循环打印,行号为endrow,列号为endcol-1到count递减。

第四步从下往上打印满足的条件是终止列号大于开始列号endcol>start且终止行号至少比开始行号大2即endrow-count>1,循环打印,行号为endrow-1到count+1递减,列号为count。

import java.util.ArrayList;
public class Solution {
    public ArrayList<Integer> result=new ArrayList<>();
    public ArrayList<Integer> printMatrix(int [][] matrix) {
        int row=matrix.length;
        int col=matrix[0].length;
        if(matrix==null || row<0 || col<0){
            return null;
        }
        int count=0;
        while(col>count*2 && row>count*2){
            PrintCircle(matrix,col,row,count);
            count++;
        }
        return result;
    }
    
    public void PrintCircle(int [][] matrix,int col,int row,int start){
        int endrow=row-start-1;
        int endcol=col-start-1;
        //从左到右打印一行
        //第一行一定会打印的
        for(int i=start;i<=endcol;i++){
            result.add(matrix[start][i]);
        }
        //从上往下打印(第二步)
        if(endrow>start){
            for(int i=start+1;i<=endrow;i++){
                result.add(matrix[i][endcol]);
            }
        }
        //从右往左打印(第三步)
        if(endrow>start && endcol>start){
            for(int i=endcol-1;i>=start;i--){
                result.add(matrix[endrow][i]);
            }
        }
        //从下往上打印(第四步)
        if((endrow-start>1)&&endcol>start){
            for(int i=endrow-1;i>=start+1;i--){
                result.add(matrix[i][start]);
            }
        }
    }
}


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值