【LeetCode每日一题】螺旋矩阵

微信公众号:程序员Alex
关注可了解更多的编程知识。问题或建议,请公众号留言;
如果你觉得文章对你有帮助,欢迎关注分享

螺旋矩阵

题目

给定一个包含 m x n 个元素的矩阵(m 行, n 列),请按照顺时针螺旋顺序,返回矩阵中的所有元素。

示例 1:

输入:
[
 [ 1, 2, 3 
],
 [ 4, 5, 6 ],
 [ 7, 8, 9 ]
]

输出: [1,2,3,6,9,8,7,4,5]

示例 2:

输入:
[
  [1, 2, 3, 4
],
  [5, 6, 7, 8],
  [9,10,11,12]
]
输出: [1,2,3,4,8,12,11,10,9,5,6,7]

分析

​ 这道题大概意思就是遍历一个m*n的二维数组,通俗点讲就是农村包围城市,最先占领外围,然后向内逼近。

​ 仔细观察可以发现,遍历方向依次是右下左上,因此我们可以从遍历方向上逐个击破。

假设有个大小为 m*n 的矩阵,解题步骤如下

  • 定义方向

    private static int DIRECTION_RIGHT = 0;
    private static int DIRECTION_DOWN = 1;
    private static int DIRECTION_LEFT = 2;
    private static int DIRECTION_UP = 3;
  • 设置障碍

    设置和原有矩阵相同的矩阵,使用 boolean 类型表示当前位置是否被遍历,如果被遍历,则视为障碍物,遍历到此处需要调整方向。

  • 分析每个方向的临界点(调整方向的位置)
    有效数指障碍物前的最后一个位置的数

    方向 临界点 避障措施
    右 遍历到一行的最后一个有效数 调头向下
    下 遍历到一列的最后一个有效数 调头向左
    左 遍历到一行的第一个有效数 调头向上
    上 遍历到一列的第一个有效数 调头向右
  • 遍历矩阵

核心代码

    public static List<Integer> spiralOrder(int[][] matrix) {
        // 特殊值校验
        if (matrix == null || matrix.length == 0 || matrix[0].length == 0) {
            return new ArrayList<>();
        }

        int m = matrix.length;
        int n = matrix[0].length;
        List<Integer> list = new ArrayList(m * n);

        // 设置遍历初始坐标和方向
        int row = 0, column = 0, direction = DIRECTION_RIGHT;

        // 设置路障
        boolean[][] obstacleArr = new boolean[m][n];

        // 遍历数组
        for (int i = 0; i < m * n; i++) {

            list.add(matrix[row][column]);
            obstacleArr[row][column] = true;

            // 向右移动
            if (direction == DIRECTION_RIGHT) {
                if (column < n - 1) {
                    column++;
                    // 避障转移
                    if (obstacleArr[row][column] == true) {
                        column--;
                        direction = DIRECTION_DOWN;
                    }
                } else {
                    direction = DIRECTION_DOWN;
                }

            }

            // 向下移动
            if (direction == DIRECTION_DOWN) {
                if (row < m - 1) {
                    row++;
                    // 避障转移
                    if (obstacleArr[row][column] == true) {
                        row--;
                        direction = DIRECTION_LEFT;
                    }
                } else {
                    direction = DIRECTION_LEFT;
                }
            }

            // 向左移动
            if (direction == DIRECTION_LEFT) {
                if (column > 0) {
                    column--;
                    // 避障转移
                    if (obstacleArr[row][column] == true) {
                        column++;
                        direction = DIRECTION_UP;
                    }
                } else {
                    direction = DIRECTION_UP;
                }
            }

            // 向上移动
            if (direction == DIRECTION_UP) {
                if (row > 0) {
                    row--;
                    // 避障转移,
                    if (obstacleArr[row][column] == true) {
                        row++;
                        // 结束了一个轮回,走内环,开始新的一轮
                        column++;
                        direction = DIRECTION_RIGHT;
                    }
                } else {
                    direction = DIRECTION_RIGHT;
                }
            }
        }
        return list;
    }

完整源码

https://github.com/tinet-shenjg/leetCode4J