题目描述
输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字,例如,如果输入如下4 × 4矩阵: 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.
分析
大致算法思路就是从左到右,从上到下,从右到左,从下到上遍历。
遍历方向共有4种,右,下,左,上。
当前遍历方向:1 表示 右,2 表示 下,3 表示 左,4 表示 上
dir为direction缩写
flagArr:定义一个二元数组记录对应位置是否已经走过
(1)向右移动到底,改变方向向下,行索引 row+1,列索引不变;
(2)向下移动到底,改变方向向左。行索引 row 不变,列索引 col-1;
(3)向左移动到底,改变方向向上,行索引 row-1,列索引不变;
(4)向上移动到底,改变方向向右,行索引 row 不变,列索引 col+1;
注:代码中为了与区分开始设置的总行数rows,总列数cols,中间行列变化用,i 与 j 表示
实现代码如下:
import java.util.*;
public class Solution {
public ArrayList<Integer> printMatrix(int[][] matrix) {
ArrayList<Integer> list = new ArrayList<Integer>();
if(matrix == null || matrix.length == 0){
return list;
}
int rows = matrix.length;
int cols = matrix[0].length;
// 1.记录元素是否已经遍历过的数组 boolean[][] flagArr,默认值均为false;
boolean[][] flagArr = new boolean[rows][cols];
// 2.遍历索引,设置初始值
int i = 0, j = -1;
// 3.当前遍历方向:1:右,2:下,3:左,4:上
int dir = 1;// 初始为向右
// 开始遍历
while (list.size() < rows * cols) {// 未遍历完
// 根据当前方向判断前进方向,即按照目前方向判断当前元素是否可以打印,分为两个一个控制方向,一个进行添加到List
if (dir == 1) {// 向右
j++;
if (j == cols || flagArr[i][j]) {// 向右超越边界或者当前元素已经遍历过
j--; // 回到前一个位置,下标表示最后一个应该是cols-1
dir = 2;// 方向变为向下
}
}
if (dir == 2) {// 向下
i++;
if (i == rows || flagArr[i][j]) {
i--;
dir = 3;// 方向变为向左
}
}
if (dir == 3) {// 向左
j--;
if (j < 0 || flagArr[i][j]) {//超过左边边界,或者当前元素已经遍历过
j++;
dir = 4;// 方向变为向上
}
}
if (dir == 4) {// 向上
i--;
if (i < 0 || flagArr[i][j]) {
i++;
dir = 1;// 方向变为向右
}
}
//没被遍历就添加
if (!flagArr[i][j]){
list.add(matrix[i][j]); //添加入list
flagArr[i][j] = true;//当前位置记为已经遍历过
}
}
return list;
}
}