转圈打印矩阵

题目:

给定一个整形矩阵matrix,请按照转圈的方式打印它。

例如:

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

要求:额外空间复杂度为O(1).

分析:如果把思路限制在局部坐标怎么变换上面,这个题就很难写了。

例如:如果遇到一个矩阵(数组)打印或者处理的题目,应该先形成一种宏观调度的思维,这牵涉到程序的设计了。那么对于这道题,给四个变量来标记左上角的点(col1,row1)和右下角的点(col2,row2),这两个点可以压中一个矩阵,如果要打印这两个点压中的矩阵的边界(最外围一圈),这个函数比较好写,col1++,加到col2的位置停下来,然后row1++,加到row2的位置停下来。然后row2--,减到row1的位置停下来,然后col2--,减到col1的位置停下来。基本函数是只打印最外围的一圈,代码如下:


public class PrintMatrixSpiralOrder {

	public static void spiralOrderPrint(int[][] matrix) {
		int row1 = 0;
		int col1 = 0;
		int row2 = matrix.length - 1; //右下角位置坐标
		int col2 = matrix[0].length - 1;
		while (row1 <= row2 && col1 <= col2) {
			printEdge(matrix, row1++, col1++, row2--, col2--);
		}
	}

	public static void printEdge(int[][] m, int row1, int col1, int row2, int col2) {
		if (row1 == row2) { //这个矩阵只有一行,只从col1打印到col2就行了。
			for (int i = col1; i <= col2; i++) {
				System.out.print(m[row1][i] + " ");
			}
		} else if (col1 == col2) { //这个矩阵只有一列,
			for (int i = row1; i <= row2; i++) {  //只打印row1到row2就行了
				System.out.print(m[i][col1] + " ");
			}
		} else { //下面代码是指矩阵不止一行或一列
			int curC = col1;
			int curR = row1;
			while (curC != col2) {
				System.out.print(m[row1][curC] + " ");
				curC++;
			}
			while (curR != row2) {
				System.out.print(m[curR][col2] + " ");
				curR++;
			}
			while (curC != col1) {
				System.out.print(m[row2][curC] + " ");
				curC--;
			}
			while (curR != row1) {
				System.out.print(m[curR][col1] + " ");
				curR--;
			}
		}
	}

	public static void main(String[] args) {
		int[][] matrix = { { 1, 2, 3, 4 }, { 5, 6, 7, 8 }, { 9, 10, 11, 12 },
				{ 13, 14, 15, 16 } };
		spiralOrderPrint(matrix);

	}

}

再例如,如果要Z字形打印矩阵,也不要局限在坐标变换里面,会疯的。代码如下:


public class ZigZagPrintMatrix {

	public static void printMatrixZigZag(int[][] matrix) {
		int row1 = 0;
		int col1 = 0;
		int row2 = 0;
		int col2 = 0;
		int endR = matrix.length - 1;
		int endC = matrix[0].length - 1;
		boolean fromUp = false;
		while (row1 != endR + 1) {
			printLevel(matrix, row1, col1, row2, col2, fromUp);
			row1 = col1 == endC ? row1 + 1 : row1;//只有col1触到最后一列时,row1才开始增加
			col1 = col1 == endC ? col1 : col1 + 1;//如果col1已经到最后就不变了,否则col1增加
			col2 = row2 == endR ? col2 + 1 : col2;
			row2 = row2 == endR ? row2 : row2 + 1;
			fromUp = !fromUp;
		}
		System.out.println();
	}

	public static void printLevel(int[][] m, int row1, int col1, int row2, int col2,
			boolean f) {
		if (f) {  //如果f为true,从右上方向左下方打印
			while (row1 != row2 + 1) { //或者写成row1 <= row2
				System.out.print(m[row1++][col1--] + " ");
			}
		} else {
			while (row2 != row1 - 1) {
				System.out.print(m[row2--][col2++] + " ");
			}
		}
	}

	public static void main(String[] args) {
		int[][] matrix = { { 1, 2, 3, 4 }, { 5, 6, 7, 8 }, { 9, 10, 11, 12 } };
		printMatrixZigZag(matrix);

	}

}

下面来说转圈打印这道题


public class RotateMatrix {

	public static void rotate(int[][] matrix) {
		int tR = 0;
		int tC = 0;
		int dR = matrix.length - 1;
		int dC = matrix[0].length - 1;
		while (tR < dR) {
			rotateEdge(matrix, tR++, tC++, dR--, dC--);
		}
	}

	public static void rotateEdge(int[][] m, int tR, int tC, int dR, int dC) {
		int times = dC - tC; 
		int tmp = 0;
		for (int i = 0; i != times; i++) {
			tmp = m[tR][tC + i];
			m[tR][tC + i] = m[dR - i][tC];
			m[dR - i][tC] = m[dR][dC - i];
			m[dR][dC - i] = m[tR + i][dC];
			m[tR + i][dC] = tmp;
		}
	}

	public static void printMatrix(int[][] matrix) {
		for (int i = 0; i != matrix.length; i++) {
			for (int j = 0; j != matrix[0].length; j++) {
				System.out.print(matrix[i][j] + " ");
			}
			System.out.println();
		}
	}

	public static void main(String[] args) {
		int[][] matrix = { { 1, 2, 3, 4 }, { 5, 6, 7, 8 }, { 9, 10, 11, 12 },
				{ 13, 14, 15, 16 } };
		printMatrix(matrix);
		rotate(matrix);
		System.out.println("=========");
		printMatrix(matrix);

	}

}

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值