[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来标记矩阵最外层位置。

  1. 初始化top、bottom、left、right为矩阵最外层

  2. 先遍历最外层顶侧从 ( t o p , l e f t ) (top, left) (top,left) ( t o p , r i g h t ) (top, right) (top,right)

  3. 再遍历最外层右侧从 ( 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)

  4. 如果 l e f t < r i g h t 且 t o p < b o t t o m left<right 且top < bottom left<righttop<bottom时才能遍历底侧与左侧

    • ( b o t t o m , r i g h t − 1 ) (bottom, right-1) (bottom,right1) ( 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) (bottom1,left) ( t o p + 1 , l e f t ) (top+1, left) (top+1,left)
  5. 更新为下一层
    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;
    }
}
posted @ 2020-06-05 10:33  消灭猕猴桃  阅读(59)  评论(0编辑  收藏  举报