顺时针打印矩阵

 

Posted by     DH on August 14, 2017

题目

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

如下图所示:

分析

这个题感觉更像是找规律,我的思想是先求出从外到内一共有多少圈,然后去输入每一圈的四条边。 求圈数,要根据矩阵短边的长度来确定,也就是如果矩阵的列数比行数少,就要根据列数去求,反之亦然。 其实这里可以看做求对脚线

对角线的长度的一半就是圈数。

上图这种情况圈数也是2;

当较短的边是奇数的时候:

这个时候的,(3-1)/2+1 = 2

在取得圈数的基础上,只要每次输入一圈就能够顺时针遍历完。

接下来要思考的就是如何控制边界。

(1) 从左往右:从左往右的时候,行是固定的,列依次增加1,也就是array[固定][依次+1]; 那么行就是第几圈,第一圈的时候,array[0][依次+1];设当前的圈数是circle,二维数组的第二个参数为columns - 0 ,第二圈时为columns - 1,依次类推;

(2) 从上往下:此时列是固定的,为columns - circle - 1;而行是从上往下依次+1的。边界是:行数 - circle。

(3) 从右往左:此时行是固定的,为rows - circle - 1。只需要依次列依次-1,边界条件是:列数 >= 当前的圈数。并且行数 != 当前的圈数, 这是对应着特殊情况,如[1,2,3,4,5];

(4)从下往上:此时列是固定的,为circle,行依次-1。

代码

public ArrayList<Integer> printMatrix(int [][] matrix) {
	       if (matrix == null || matrix.length == 0) {
			return null;
		}
	       
	    ArrayList <Integer> resultList = new ArrayList<>();
	    
	    // 列数
	    int colums = matrix[0].length;
	    // 行数
	    int rows = matrix.length;
	    
	    // 计算圈数
	    int countOfCircle = 0;
	    if (colums < rows) {
			countOfCircle = (colums - 1)/2 + 1;
		}else{
			countOfCircle = (rows - 1)/2 +1;
		}
	    
	    for(int circle = 0;circle < countOfCircle;circle++){
	    
	    		// 从左到右
	    		for(int first = circle;first < colums -circle;first++){
	    			resultList.add(matrix[circle][first]);
	    		}
	    		
	    		// 从上到下
	    		for(int second = circle + 1; second <rows-circle;second++){
	    			resultList.add(matrix[second][colums -circle -1]);
	    		}
	    	
	    		// 从右到左
	    		for(int third = colums - 2 - circle ; third >= circle && (rows - circle - 1 != circle) ; third --){
	    			resultList.add(matrix[rows - circle -1][third]);
	    		}
	    		
	    		//从下到上
	    		for(int fourth = rows - circle - 2; fourth > circle && (colums -circle - 1 != circle);fourth--){
	    			resultList.add(matrix[fourth][circle]);
	    		}
	    }
	    
	    return resultList;
    }