本文参考左老师算法课内容
打印矩阵题比较常见的有以下几道:
59. 螺旋矩阵 II
54. 螺旋矩阵
剑指 Offer 29. 顺时针打印矩阵
48. 旋转图像
之字形打印矩阵
总体来说,做矩阵相关题目时,需要宏观看待整个变化过程。
先多模拟几个用例找到其规律,再开始写代码
59. 螺旋矩阵 II
将大矩阵可以看作由一圈圈小矩阵组成,只要逐层将矩阵内的数字填好,那么大矩阵也就填好了。
对于每一圈小矩阵,可以将其分解为四个子矩阵,相当于矩形的四条边。
(x1,y1)->-(1)->-
| |
| |
(4) (2)
| |
⬆️ ⬇️
| |
--<-(3)-<--(x2,y2)
class Solution {
public int number = 1;
public int[][] generateMatrix(int n) {
int [][]res= new int[n][n];
int startX=0;
int startY=0;
int endX=n-1;
int endY=n-1;
while(startX<=endX){
generate(res,startX++,startY++,endX--,endY--);
}
return res;
}
private void generate( int[][] res, int x1, int y1, int x2, int y2 ) {
//行
for(int i=y1;i<=y2;i++){
res[x1][i]=number++;
}
//列
for ( int i =x1+1;i<=x2;i++ ){
res[i][y2]=number++;
}
// 行 《----
for ( int i = y2-1; i >=y1 ; i-- ) {
res[x2][i]=number++;
}
// 列
for ( int i = x2-1; i >x1 ; i-- ) {
res[i][y1]=number++;
}
}
}
54. 螺旋矩阵
本题中,需要注意的是,如果只剩一行或者一列,应该要特殊处理,要不然会产生数组越界的bug。
public List<Integer> list = new ArrayList<>();
public List<Integer> spiralOrder(int[][] matrix) {
int m=matrix.length-1;
int n=matrix[0].length-1;
int x=0;
int y=0;
while ( x<=m && y<=n){
generate(matrix,x++,y++,m--,n--);
}
return list;
}
private void generate( int[][] matrix, int x, int y, int m, int n ) {
if(x==m ){
for ( int i = y; i <=n ; i++ ) {
list.add( matrix[x][i] );
}
}else if(y==n){
for ( int i = x; i <=m ; i++ ) {
list.add( matrix[i][y] );
}
}else{
// 行
for(int i=y;i<=n;i++){
list.add( matrix[x][i] );
}
//列
for ( int i = x+1; i <=m ; i++ ) {
list.add( matrix[i][n] );
}
// 行 《--
for ( int i = n-1; i >=y ; i-- ) {
list.add( matrix[m][i] );
}
// 列
for ( int i = m-1; i >x; i-- ) {
list.add( matrix[i][y] );
}
}
}
48. 旋转图像
public static void rotate( int[][] matrix ) {
int x = 0;
int y = 0;
int endX = matrix.length - 1;
int endY = matrix[0].length - 1;
while ( x < endX ) {
rotateArr( matrix, x++, y++, endX--, endY-- );
}
}
private static void rotateArr( int[][] matrix, int x, int y, int endX, int endY ) {
int temp = 0;
for ( int i = 0; i < endY - y; i++ ) {
//保存第一行的数
temp = matrix[x][y + i];
// 将第一列的数给第一行
matrix[x][y + i] = matrix[endX - i][y];
// 将最后一行的数 给第一列
matrix[endX - i][y] = matrix[endX][endY - i];
// 将最后一列的数 给最后一行
matrix[endX][endY - i] = matrix[x + i][endY];
// 将 第一行的数 给最后一列
matrix[x + i][endY] = temp;
}
}
之字形打印矩阵
/*
给定一个矩阵matrix,
按照“之”字形的方式打印这个矩阵。例如
1,8,6,7
2,6,4,11
3,5,9,10
打印结果是1,8,2,3,6,6,7,4,5,9,11,10。
要求额外空间复杂度是O(1)。
*/
public static List<Integer> list = new ArrayList<>();
private static void printByZ( int[][] arr ) {
int m = arr.length - 1;
int n = arr[0].length - 1;
int a = 0;
int b = 0;
int c = 0;
int d = 0;
// 是否从下往上
boolean f = true;
while ( b <= n ) {
int printB = a == m ? b++ : b;
int printA = a == m ? m : a++;
int printC = d == n ? c++ : c;
int printD = d == n ? d : d++;
add( arr, printA, printB, printC, printD, f );
f = !f;
}
}
private static void add( int[][] arr, int printA, int printB, int printC, int printD, boolean f ) {
//从下往上
if ( f == true ) {
for ( int i = printA; i >= printC; i-- ) {
list.add( arr[i][printB++] );
}
} else {
for ( int i = printC; i <= printA; i++ ) {
list.add( arr[i][printD--] );
}
}
}
public static void main( String[] args ) {
int[][] arr = new int[][]{
{ 1, 8, 6 }, { 2, 6, 4 }, { 3, 5, 9 }
};
printByZ( arr );
for ( Integer i : list
) {
System.out.printf( "%3d", i );
}
}