[LeetCode]面试题29.顺时针打印矩阵
解法一
解法一通过模拟运动路径打印矩阵,通过判断下个位置是否越界、下个位置是否已访问来控制顺时针旋转。判断元数位置是否已经访问需要用到一个辅助数组visited,每访问一个位置就把visited对应位置进行标记。
java
class Solution {
public int[] spiralOrder(int[][] matrix) {
if(matrix == null || matrix.length == 0 || matrix[0].length == 0){
return new int[0];
}
int[] ans = new int[matrix.length * matrix[0].length];
int rows = matrix.length;//矩阵的行数
int cols = matrix[0].length;//矩阵的列数
int total = rows * cols;//矩阵的总元数个数
boolean[][] visited = new boolean[rows][cols];//定义一个辅助数组用于记录该位置是否被访问过
int row = 0, col = 0;//一开始从左上角开始
int[][] directions = {{0,1},{1,0},{0,-1},{-1,0}};//方向数组用于控制row与col移动
int directionIndex = 0;//用于方向切换默认向右移动
for(int i = 0; i < total; i++){
ans[i] = matrix[row][col];
visited[row][col] = true;//标记辅助数组表示该位置已经访问过
int nextRow = row + directions[directionIndex][0];//nextRow,nextCol用于指定下一个位置判断越界、
int nextCol = col + directions[directionIndex][1];//和访问的情况
if(nextRow < 0 || nextRow >= rows || nextCol < 0 || nextCol >= cols || visited[nextRow][nextCol]){
//出现越界或者下个位置的元数已访问的情况就切换方向
directionIndex = (directionIndex + 1)%4;
}
row += directions[directionIndex][0];
col += directions[directionIndex][1];
}
return ans;
}
}
解法二
解法二通过按层模拟来打印矩阵,每次按照顺时针的顺序打印最外层,使用top、bottom、left、right来标记矩阵最外层位置。
-
初始化top、bottom、left、right为矩阵最外层
-
先遍历最外层顶侧从 ( t o p , l e f t ) (top, left) (top,left)到 ( t o p , r i g h t ) (top, right) (top,right)
-
再遍历最外层右侧从 ( t o p + 1 , r i g h t ) (top+1, right) (top+1,right)到 ( b o t t o m , r i g h t ) (bottom, right) (bottom,right)
-
如果 l e f t < r i g h t 且 t o p < b o t t o m left<right 且top < bottom left<right且top<bottom时才能遍历底侧与左侧
- 从 ( b o t t o m , r i g h t − 1 ) (bottom, right-1) (bottom,right−1)到 ( b o t t o m , l e f t ) (bottom, left) (bottom,left)
- 从 ( b o t t o m − 1 , l e f t ) (bottom-1, left) (bottom−1,left)到 ( t o p + 1 , l e f t ) (top+1, left) (top+1,left)
-
更新为下一层
top++;
bottom–;
left++;
right–;
java
class Solution {
public int[] spiralOrder(int[][] matrix) {
if(matrix == null || matrix.length == 0 || matrix[0].length == 0){
return new int[0];
}
int[] ans = new int[matrix.length * matrix[0].length];
int rows = matrix.length;//矩阵的行数
int cols = matrix[0].length;//矩阵的列数
int left = 0, top = 0, right = cols - 1, bottom = rows - 1;
int index = 0;
while(top <= bottom && left <= right){
//顶侧和右侧是肯定需要遍历的
for(int col = left; col <= right; col++){//遍历最外层顶侧
ans[index++] = matrix[top][col];
}
for(int row = top+1; row <= bottom; row++){//遍历最外层右侧
ans[index++] = matrix[row][right];
}
//left < right时从右往左遍历才有意义,如果left = right,说明最内层矩阵只有一列,上面两步已经将最外层遍历过了,
//top < bottom时从底部往上遍历才有意义,如果top = bottom,说明最内层矩阵只有一行, 上面两步已经将最外层遍历过了
if(left < right && top < bottom){
for(int col = right-1; col >= left; col--){//从右往左遍历
ans[index++] = matrix[bottom][col];
}
for(int row = bottom -1; row > top; row--){//从下往上遍历
ans[index++] = matrix[row][left];
}
}
//更新为下一层
top++;
bottom--;
left++;
right--;
}
return ans;
}
}