leetcode
leetcode 51 ~ 100
螺旋矩阵

螺旋矩阵

难度:

标签:

题目描述

给你一个 mn 列的矩阵 matrix ,请按照 顺时针螺旋顺序 ,返回矩阵中的所有元素。

 

示例 1:

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

示例 2:

输入:matrix = [[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 == matrix.length
  • n == matrix[i].length
  • 1 <= m, n <= 10
  • -100 <= matrix[i][j] <= 100

代码结果

运行时间: 36 ms, 内存: 14.8 MB


/*
 * 思路:
 * 1. 利用Stream流的特性实现螺旋遍历。
 * 2. 通过Stream.of()创建流,按顺序访问矩阵的四个边界元素。
 * 3. 利用flatMap和collect方法,将遍历结果收集到列表中。
 */
 
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import java.util.stream.Stream;
 
public class SpiralOrderStream {
    public List<Integer> spiralOrder(int[][] matrix) {
        if (matrix == null || matrix.length == 0) return new ArrayList<>();
        List<Integer> result = new ArrayList<>();
        int m = matrix.length, n = matrix[0].length;
        int left = 0, right = n - 1, top = 0, bottom = m - 1;
        while (left <= right && top <= bottom) {
            Stream.of(
                IntStream.rangeClosed(left, right).map(i -> matrix[top][i]).boxed().collect(Collectors.toList()),
                IntStream.rangeClosed(top + 1, bottom).map(i -> matrix[i][right]).boxed().collect(Collectors.toList()),
                IntStream.rangeClosed(left, right).map(i -> matrix[bottom][right - i + left]).boxed().collect(Collectors.toList()),
                IntStream.rangeClosed(top + 1, bottom).map(i -> matrix[bottom - i + top + 1][left]).boxed().collect(Collectors.toList())
            ).flatMap(List::stream).forEach(result::add);
            top++; right--; bottom--; left++;
        }
        return result;
    }
}

解释

方法:

这个题解采用了螺旋遍历矩阵的方法。初始化矩阵的上下左右四个边界,然后按照右、下、左、上的顺序依次遍历并收缩边界,直到遍历完整个矩阵。具体做法是:先从左到右遍历上边界,然后上边界下移;再从上到下遍历右边界,然后右边界左移;接着从右到左遍历下边界,然后下边界上移;最后从下到上遍历左边界,然后左边界右移。如此循环直至越过边界,遍历结束。

时间复杂度:

O(m*n)

空间复杂度:

O(m*n)

代码细节讲解

🦆
在螺旋矩阵代码中,当某个方向的遍历完成后,边界如何确保不会影响到下一次遍历?
在代码中,每次完成一个方向的遍历后,相应的边界会进行调整(例如上边界在遍历完后会下移,右边界在遍历完后会左移等)。这种调整确保了下一次遍历不会重复访问已遍历过的元素,并且边界的调整也作为循环停止的条件之一,当新的边界越过对面的边界时,循环会停止。这样,每个方向的遍历都只处理当前有效的区域,不会影响到下一次遍历。
🦆
如何处理矩阵的特殊情况,比如单行或单列的情况,在螺旋遍历时边界条件会有何不同?
在单行或单列的矩阵情况下,螺旋遍历的边界调整会迅速导致循环的结束。例如,对于单行矩阵,首次遍历右边界(即整行)后,上边界下移会立即超过下边界,触发循环结束条件。对于单列矩阵,首次遍历下边界(即整列)后,右边界左移会立即超过左边界,同样触发循环结束。这意味着在这些特殊情况下,部分遍历方向可能根本不会执行。
🦆
代码中每次遍历完一个方向后都进行了边界的调整,这样的处理方式是否可能导致重复访问某些元素?
由于边界在每次遍历后都进行了适当的调整,例如上边界遍历完后即下移,这样的调整避免了下一轮遍历时重复访问已经遍历过的元素。每次边界调整后的检查条件(比如 'if u > d' 或 'if l > r')确保了一旦新的边界越过了对应的对面边界,相关方向的遍历便会停止,从而阻止了重复访问。
🦆
在提供的题解中,存在多个循环结构,这些循环的停止条件是如何设计的,以确保不会超出矩阵的边界?
循环的停止条件是通过边界的相对位置来设计的。每次遍历一个方向结束时,都会对该方向的边界进行调整,然后检查是否新的边界已经越过了相对的边界(例如上边界是否已越过下边界,或左边界是否已越过右边界)。这些检查作为循环的停止条件,确保了遍历过程不会超出矩阵边界或重复访问元素。每个循环在进入之前都进行这样的条件判断,从而保持遍历的正确性和安全性。

相关问题

螺旋矩阵 II

给你一个正整数 n ,生成一个包含 1 到 n2 所有元素,且元素按顺时针顺序螺旋排列的 n x n 正方形矩阵 matrix

 

示例 1:

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

示例 2:

输入:n = 1
输出:[[1]]

 

提示:

  • 1 <= n <= 20