矩阵处理技巧
这类技巧用于应对题目要求的奇怪的方式打印矩阵信息。
经典问题
zigzag打印矩阵
转圈打印矩阵
原地旋转正方形矩阵
zigzag打印矩阵
以图中红线顺序打印矩阵信息。可以设定两个锚点A,B用于宏观调控轨迹。可以把上述轨迹看成一段段斜线,只需要确定该斜线方向是从上到下还是从下到上打印,打印斜线可以抽象为一个方法,因为打印方向很好确定,就是交替进行。
A,B两个锚点的运行轨迹如下图,A一直向右,直到到头了再向下移动;B一直向下,直到到头了再向右移动,最终都会到达右下角。
public static void zigZag(int[][] matrix){
int endRow = matrix.length - 1, endCol = matrix[0].length - 1;
boolean topToBottom = false; // 最开始是从下到上
int Arow = 0, Acol = 0; // 锚点A
int Brow = 0, Bcol = 0; // 锚点B
while (Arow != endRow + 1){
printLine(matrix, Arow, Acol, Brow, Bcol, topToBottom);
Arow = Acol == endCol ? Arow + 1 : Arow;
Acol = Acol == endCol ? Acol : Acol + 1;
Bcol = Brow == endRow ? Bcol + 1 : Bcol;
Brow = Brow == endRow ? Brow : Brow + 1;
topToBottom = !topToBottom;
}
}
private static void printLine(int[][] matrix, int arow, int acol, int brow, int bcol, boolean topToBottom) {
if (topToBottom){
while (arow != brow + 1){
System.out.print(matrix[arow++][acol--] + "\t");
}
} else {
while (bcol != acol + 1)
System.out.print(matrix[brow--][bcol++] + "\t");
}
System.out.println();
}
旋转打印矩阵
以图中红线顺序旋转打印矩阵。首先可以将轨迹拆分成一层一层,再在每层上拆成一段一段。如下两图:
这种调度方式里,左上角和右下角的点作为锚点来判断轨迹的运行。每一层的起点都是行数+1,列数+1;而每一层的终点都是行数-1,列数-1。绘制一层的时候,有时会遇到两种特殊情况:
1. 只剩下一条水平线的时候
1. 只剩下一条垂直线的时候
public static void Circle(int[][] matrix){
int startR = 0, startC = 0;
int endR = matrix.length - 1, endC = matrix[0].length - 1;
while (startR <= endR && startC <= endC){
printLayer(matrix, startR++, startC++, endR--, endC--);
System.out.println();
}
}
private static void printLayer(int[][] matrix, int startR, int startC, int endR, int endC) {
if (startR == endR){ // 水平线
while (startC <= endC)
System.out.print(matrix[startR][startC++] + "\t");
} else if (startC == endC) { // 垂直线
while (startR <= endR)
System.out.print(matrix[startR++][startC] + "\t");
} else { // 正常情况
int SC = startC, SR = startR;
while (startC < endC)
System.out.print(matrix[startR][startC++] + "\t");
while (startR < endR)
System.out.print(matrix[startR++][startC] + "\t");
while (startC > SC)
System.out.print(matrix[startR][startC--] + "\t");
while (startR > SR)
System.out.print(matrix[startR--][startC] + "\t");
}
}
正方形矩阵的旋转问题
假如有一个方阵,现在要原地进行数据的顺时针旋转90度。原地就是说利用的还是本身这个矩阵空间,不可以开辟新的矩阵空间。示意图如下:
可以将这种变化按圈分割:最外层的元素旋转之后肯定都还在最外层,同样层的元素旋转之后不可能改变层的位置,所以将轨迹变化按层拆解。现在就拿最外层的元素来举例:
该层正方形边长为 4 4 4 ,那么就可以将元素分成 3 3 3组 ,每一组都用不同的记号标注了,相同的记号表示为同一组。每一组的元素只需要按顺时针方向填值即可。
public static void rotate(int[][] matrix){
int startR = 0, startC = 0;
int endR = matrix.length - 1, endC = matrix[0].length - 1;
while (startR <= endR && startC <= endC)
rotateLayer(matrix, startR++, startC++, endR--, endC--);
}
private static void rotateLayer(int[][] matrix, int startR, int startC, int endR, int endC) {
int groups = endC - startC; // 分成的组数
int tmp = 0;
for (int i = 0; i < groups; i++) {
tmp = matrix[startR][startC + i];
matrix[startR][startC + i] = matrix[endR - i][startC];
matrix[endR - i][startC] = matrix[endR][endC - i];
matrix[endR][endC - i] = matrix[startR + i][endC];
matrix[startR + i][endC] = tmp;
}
}
核心技巧:找到一种宏观调度方式,不要局限于坐标的变化