之字形打印矩阵。
之字形打印矩阵 - 牛客网
题目
对于一个矩阵,请设计一个算法,将元素按“之”字形打印。具体见样例。
给定一个整数矩阵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);
} }
|