LeetCode 54. 螺旋矩阵 Java实现

54. 螺旋矩阵

题目来源

54. 螺旋矩阵

题目分析

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

题目难度

  • 难度:中等

题目标签

  • 标签:数组、矩阵

题目限制

  • m == matrix.length
  • n == matrix[i].length
  • 1 <= m, n <= 10
  • -100 <= matrix[i][j] <= 100

解题思路

思路:模拟螺旋过程

  1. 问题定义
    • 需要按照顺时针螺旋顺序遍历矩阵并返回所有元素。
  2. 核心算法
    • 使用四个变量分别表示矩阵的左、右、上、下边界。
    • 通过循环逐步缩小边界,模拟螺旋遍历的过程。
  3. 关键步骤
    • 遍历矩阵的上边界,并向右移动。
    • 遍历矩阵的右边界,并向下移动。
    • 如果还有剩余行和列,遍历矩阵的下边界,并向左移动。
    • 如果还有剩余行和列,遍历矩阵的左边界,并向上移动。
    • 收缩边界,重复上述过程,直到遍历完所有元素。

核心算法步骤

  1. 初始化边界
    • leftrighttopbottom 分别表示矩阵的左、右、上、下边界。
  2. 遍历并收缩边界
    • While循环,条件为 left <= right && top <= bottom
    • 遍历上边界,从左到右。
    • 遍历右边界,从上到下。
    • 如果内层还有空间,遍历下边界,从右到左。
    • 如果内层还有空间,遍历左边界,从下到上。
    • 收缩边界:left++right--top++bottom--
  3. 返回结果
    • 将遍历到的元素添加到结果列表中,最后返回该列表。

代码实现

以下是 Java 代码实现:

/**
 * 54. 螺旋矩阵
 * @param matrix 矩阵
 * @return List<Integer> 顺时针螺旋顺序
 */
public List<Integer> spiralOrder(int[][] matrix) {
    List<Integer> ans = new ArrayList<>();
    int m = matrix.length;
    int n = matrix[0].length;
    int left = 0, right = n - 1, top = 0, bottom = m - 1;
    while (left <= right && top <= bottom) {
        for (int i = left; i <= right; i++) {
            ans.add(matrix[top][i]);
        }
        for (int i = top + 1; i <= bottom; i++) {
            ans.add(matrix[i][right]);
        }
        if (left < right && top < bottom) {
            for (int i = right - 1; i > left; i--) {
                ans.add(matrix[bottom][i]);
            }
            for (int i = bottom; i > top; i--) {
                ans.add(matrix[i][left]);
            }
        }
        left++;
        right--;
        top++;
        bottom--;
    }
    return ans;
}

代码解读

  • 边界初始化:设置初始的左、右、上、下边界。
  • 遍历过程:通过四个for循环分别遍历矩阵的四个边界,并在每次遍历后收缩边界。
  • 边界条件:在内层遍历前检查是否还有剩余的行和列,以避免重复遍历。

性能分析

  • 时间复杂度:O(m*n),其中m和n分别是矩阵的行数和列数。每个元素都被访问一次。
  • 空间复杂度:O(1),除了用于存储结果的列表外,使用的额外空间是常数级别的。

测试用例

你可以使用以下测试用例来验证代码的正确性:

// 测试用例1
int[][] matrix1 = {
    {1, 2, 3},
    {4, 5, 6},
    {7, 8, 9}
};
System.out.println(spiralOrder(matrix1)); // 输出: [1, 2, 3, 6, 9, 8, 7, 4, 5]
// 测试用例2
int[][] matrix2 = {
    {1, 2, 3, 4},
    {5, 6, 7, 8},
    {9, 10, 11, 12}
};
System.out.println(spiralOrder(matrix2)); // 输出: [1, 2, 3, 4, 8, 12, 11, 10, 9, 5, 6, 7]
// 测试用例3
int[][] matrix3 = {
    {1}
};
System.out.println(spiralOrder(matrix3)); // 输出: [1]
// 测试用例4
int[][] matrix4 = {
    {1, 2},
    {3, 4}
};
System.out.println(spiralOrder(matrix4)); // 输出: [1, 2, 4, 3]
// 测试用例5
int[][] matrix5 = {
    {1, 2, 3},
    {4, 5, 6}
};
System.out.println(spiralOrder(matrix5)); // 输出: [1, 2, 3, 6, 5, 4]

扩展讨论

其他实现

  • 递归方法:虽然递归可以实现螺旋矩阵的遍历,但可能会增加代码的复杂度,并且对于这个问题,迭代方法已经足够清晰和高效。
  • 方向数组:使用方向数组来控制遍历的方向,可以简化边界检查的逻辑,但总体思路与上述方法类似。

性能优化

  • 空间优化:在上述实现中,我们已经做到了空间复杂度为O(1),除了输出列表外没有使用额外的空间。
  • 边界检查:在遍历内层边界时,通过条件判断避免了重复遍历,这是性能优化的一部分。

总结

这道题目考察了对矩阵遍历的理解和实现能力。通过模拟螺旋遍历的过程,我们可以有效地解决这个问题。在实际应用中,类似的矩阵操作可能会用于图像处理、数据转换等领域。掌握这种遍历方式对于解决更复杂的问题具有重要的基础意义。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值