leetcode54. 螺旋矩阵----------中等

题目

给定一个包含 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]

来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/spiral-matrix
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

第一种解法

思路:

顺时针旋转得话就应该先是从左到右,从上到下,从右到左,从下到上
问题来了怎么才能实现这个方法呢
 1.访问过的会再访问一次怎么区分呢
💡 可以设置标记数组,和已知数组下标一样,用来标记是否访问过
 2.方向怎么改变呢,什么时候变呢
💡 可以来一个二维数组专门用来改变方向的
	从左到右 行不变 列+1     {0,1}
	从上到下 行+1    列不变  {1,0}
	从右到左 行不变 列-1      {0,-1}
	从下到上 行-1     列不变  {-1,0}

	改变的条件:下边越界或者已经标记过的时候就该换方向了

代码:

public static List<Integer> spiralOrder(int[][] matrix) {
        List<Integer> order = new ArrayList<>();
        int rows = matrix.length, columns = matrix[0].length;
        if (matrix == null || rows == 0 || columns == 0) {
            return order;
        }
        // 定义标记数组
        boolean[][] visited = new boolean[rows][columns];
        // 定义遍历的方向
        int[][] directon = { { 0, 1 }, { 1, 0 }, { 0, -1 }, { -1, 0 } };
        // 定义方向的初始值
        int directionIndex = 0;
        int row = 0, col = 0;
        int total = rows * columns;
        for (int i = 0; i < total; i++) {
            // 将该元素加入到order中
            order.add(matrix[row][col]);
            // 标记
            visited[row][col] = true;
            // 定位下一行,下一列
            int nextRow = row + directon[directionIndex][0];
            int nextCol = col + directon[directionIndex][1];
            // 判断是否符合标准,越界或者标记过
            if (nextRow >= rows || nextRow < 0 || nextCol >= columns || nextCol < 0
                    || visited[nextRow][nextCol] == true) {
                // if (nextRow >= rows || nextCol >= columns || visited[nextRow][nextCol] ||
                // nextCol < 0 || nextRow < 0) {
                // 原来的方向行不通了,该换个方向了
                // direction 一共有4行即4个方向,模4防止下标越界
                directionIndex = (directionIndex + 1) % 4;
            }
            row = row + directon[directionIndex][0];
            col = col + directon[directionIndex][1];
        }
        return order;

    }

复杂度分析:

	时间复杂度:O(mn),m 和 n 是输入矩阵的行数和列数。

	空间复杂度:O(mn),需要创建一个大小和matrix相同的的二维数组visited用来记录每个位置是否被访问过。
第二种解法:按层模拟

思路:

按层模拟遍历顺序  : 上侧(从左到右) 
					右侧(从上到下) 
					下侧(从右到左) 
					左侧(从下到上)
怎么实现呢?
💡 可以设置坐标,用坐标来表示呀四个角的坐标分别是:
			左上角:(top,left)
			右上角:(top,right) 
			右下角:(bottom,right) 
			左下角:(bottom,left)
	遍历顺序就应该是:
			上侧 : (top,left)-->(top,right) 
			右侧 : (top+1,right) -->(bottom,right) 
			下侧 : (bottom,right-1) -->(bottom,left)
			左侧 : (bottom,left)-->(top+1,left)

代码:

public static List<Integer> spiralOrder(int[][] matrix) {
        List<Integer> order = new ArrayList<>();
        int rows = matrix.length, cols = matrix[0].length;
        int top = 0, bottom = rows - 1, left = 0, right = cols - 1;
        if (matrix == null || rows == 0 || cols == 0) {
            return order;
        }
        while (left <= right && top <= bottom) {
            // 遍历上侧
            for (int colsh = left; colsh <= right; colsh++) {
                order.add(matrix[top][colsh]);
            }
            // 遍历右侧
            for (int row = top + 1; row <= bottom; row++) {
                order.add(matrix[row][right]);
            }
            if (left < right && top < bottom) {
                // 遍历下侧
                for (int colx = right - 1; colx > left; colx--) {
                    order.add(matrix[bottom][colx]);
                }
                // 遍历左侧
                for (int rowz = bottom; rowz > top; rowz--) {
                    order.add(matrix[rowz][left]);
                }
            }
            top++;
            left++;
            right--;
            bottom--;
        }
        return order;

复杂度分析:

时间复杂度:O(mn),m 和 n 是输入矩阵的行数和列数

空间复杂度:O(1)。除了order以外,空间复杂度是常数。
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值