题目:
给定一个整形矩阵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);
}
}