之字形打印矩阵

之字形打印矩阵。

之字形打印矩阵 - 牛客网

题目

对于一个矩阵,请设计一个算法,将元素按“之”字形打印。具体见样例。

给定一个整数矩阵mat,以及他的维数 $n \times m$,请返回一个数组,其中元素依次为打印的数字。

测试样例:[[1,2,3],[4,5,6],[7,8,9],[10,11,12]],4,3

返回:[1,2,3,6,5,4,7,8,9,12,11,10]

解答[Java]:

核心思想

一行一行地遍历,判断当前行是偶数行还是奇数行(第一行看作第 0 行,算作偶数行)。偶数行正向打印,奇数行倒着打印。

代码

本代码中使用位运算来判断是奇数行还是偶数行,效率更高一些。

1
2
3
4
5
6
7
8
9
10
11
12
public class Printer {
public int[] printMatrix(int[][] mat, int n, int m) {
int[] ans = new int[n * m];
int flag = 0;
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
ans[flag++] = mat[i][Math.abs((i & 1) * (m - 1) - j)];
}
}
return ans;
}
}

拓展

题目升级:要求斜着按照副对角线迂回打印。

比如对于矩阵:

1
2
3
1  2  3  4
5 6 7 8
9 10 11 12

输出:

1
1 2 5 9 6 3 4 7 10 11 8 12

核心思路

对于每一条副对角线,使用 r1, c1 表示右上角的点,使用 r2, c2 表示左下角的点,然后交替从下往上打印和从上往下打印。

两个点的坐标变换逻辑是这样的,对于 r1, c1,在 c1 等于最后一列之前,c1 一直加1,在 c1 等于最后一列之后,r1 一直加1。当 r1 大于最后一行的时候,打印循环结束。r2, c2 的坐标变换逻辑类似。

完整带测试代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
public class Solution {
public static void printMatrixZigZag(int[][] matrix) {
int r1 = 0;
int c1 = 0;
int r2 = 0;
int c2 = 0;
int theLastRow = matrix.length - 1;
int theLastColumn = matrix[0].length - 1;
boolean fromUp = false;
while (r1 <= theLastRow) {
printLevel(matrix, r1, c1, r2, c2, fromUp);
r1 = (c1 == theLastColumn) ? r1 + 1 : r1;
c1 = (c1 == theLastColumn) ? c1 : c1 + 1;
c2 = (r2 == theLastRow) ? c2 + 1 : c2;
r2 = (r2 == theLastRow) ? r2 : r2 + 1;
fromUp = !fromUp;
}
System.out.println();
}

public static void printLevel(int[][] m, int r1, int c1, int r2, int c2,
boolean fromUp) {
if (fromUp) {
while (r1 <= r2) {
System.out.print(m[r1++][c1--] + " ");
}
} else {
while (r2 >= r1) {
System.out.print(m[r2--][c2++] + " ");
}
}
}

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

}
}