Leetcode: Spiral Matrix. Java

Given a matrix of m x n elements (m rows, n columns), return all elements of the matrix in spiral order.

For example,
Given the following matrix:

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

You should return [1,2,3,6,9,8,7,4,5].


public class Solution {
    public List<Integer> spiralOrder(int[][] matrix) {
        List<Integer> res = new ArrayList<Integer>();
        int m = matrix.length;
        if(m == 0) return res;
        int n = matrix[0].length;
        //循环次数小于m/2和n/2
        for(int i = 0; i < m/2 && i < n/2; i++){
            for(int j = 0; j < n - 1 - i * 2; j++)
                res.add(matrix[i][i+j]);
            for(int j = 0; j < m - 1 - i * 2; j++)
                res.add(matrix[i+j][n-i-1]);
            for(int j = 0; j < n - 1 - i * 2; j++)
                res.add(matrix[m-i-1][n-i-1-j]);
            for(int j = 0; j < m - 1 - i * 2; j++)
                res.add(matrix[m-i-1-j][i]);
        }
        //循环结束后假设行数/列数是奇数,则还剩一行/列
        if(m % 2 != 0 && m <= n){
            for(int j = 0; j < n - (m/2) * 2; j++)
                res.add(matrix[m/2][m/2+j]);  
        }
        else if(n % 2 != 0 && m > n){
            for(int j = 0; j < m - (n/2) * 2; j++)
                 res.add(matrix[n/2+j][n/2]);
        }
        return res;
    }
}


<think>我们正在处理的是LeetCode54题:螺旋矩阵。给定一个mxn的矩阵,按照螺旋顺序返回矩阵中的所有元素。根据引用内容,我们可以采用模拟螺旋路径的方法,使用方向数组来控制移动方向,当遇到边界或已访问的元素时改变方向。算法步骤:1.定义方向数组DIRS,表示右、下、左、上四个方向(顺时针)。2.初始化一个与输入矩阵同样大小的visited矩阵(或者修改原矩阵标记已访问)?但引用[1]中使用了将访问过的位置标记为Integer.MAX_VALUE的方法,这样可以在原矩阵上操作,避免额外空间。但注意题目要求不能修改原矩阵?题目没有明确,但通常我们应避免修改原数据。不过引用[1]的方法修改了原矩阵,如果要求不修改,则需要额外空间。3.另一种方法是使用边界收缩法(引用[3]提到),但引用[1]的方法更简洁。然而,题目要求返回列表,不要求保留原矩阵,所以我们可以修改原矩阵(但题目没有说可以修改,所以最好不修改?)。但引用[1]的解法修改了原矩阵。我们也可以使用一个visited数组来记录访问过的位置,这样就不修改原矩阵。考虑到题目矩阵大小不超过10x10,使用额外空间是可以接受的。但引用[1]的方法已经比较高效,且代码简洁。这里我们采用引用[1]的方法,但注意题目中矩阵元素可能包含负数,所以标记值不能是Integer.MIN_VALUE?因为题目中元素范围在-100到100,所以我们可以使用一个超出这个范围的值(比如101或Integer.MAX_VALUE)作为标记。但是,题目没有说不能修改原矩阵,所以我们可以使用。但是,如果我们不想修改原矩阵,我们可以使用一个同样大小的boolean数组来记录访问情况。两种方法都可以,这里我们提供两种实现,但根据引用[1],我们先给出修改原矩阵的实现(因为代码简洁),然后再提供一个不修改原矩阵的实现(使用边界收缩法)。不过,引用[3]提到边界收缩法,我们也可以实现。由于问题要求包含输入输出示例,我们将提供:1.算法实现(两种方法)2.输入输出示例方法一:模拟路径(修改原矩阵)-使用方向数组,按顺序向右、向下、向左、向上移动。-当下一步到达矩阵边界或已经访问过的位置时,改变方向(通过取余循环切换方向)。-使用一个变量记录当前方向,每次移动后判断下一步是否需要转向。方法二:边界收缩法(不修改原矩阵)-定义四个边界:上边界top=0,下边界bottom=m-1,左边界left=0,右边界right=n-1。-按照顺时针方向遍历:1.从左到右遍历上边界(top行),遍历完上边界下移(top++)2.从上到下遍历右边界(right列),遍历完右边界左移(right--)3.从右到左遍历下边界(bottom行),遍历完下边界上移(bottom--)4.从下到上遍历左边界(left列),遍历完左边界右移(left++)-循环条件:top<=bottom且left<=right方法二更直观,且不需要修改原矩阵,也不需要额外的标记数组,空间复杂度O(1)(除了输出列表)。我们选择方法二作为主要实现,因为它更符合题目要求(不修改原矩阵)且高效。下面给出Java实现:方法二:边界收缩法步骤:初始化top=0,bottom=m-1,left=0,right=n-1。初始化结果列表ans。while(top<=bottom&&left<=right){1.从左到右:遍历top行的left到right列,将元素加入ans。然后top++。2.从上到下:遍历right列的top到bottom行,将元素加入ans。然后right--。3.检查是否还有行(因为top可能已经超过bottom):从右到左:遍历bottom行的right到left列(逆序),将元素加入ans。然后bottom--。4.检查是否还有列:从下到上:遍历left列的bottom到top行(逆序),将元素加入ans。然后left++。}注意:在第3步和第4步之前,需要检查是否还有行/列,因为可能已经遍历完了(比如只有一行或一列的情况)。具体代码:输入输出示例:输入: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]代码实现:</think>### LeetCode 54:螺旋矩阵 Java 实现 #### 问题描述 给定一个 m×n 的矩阵,按照顺时针螺旋顺序返回矩阵中的所有元素。 **示例输入**: ```java int[][] 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] ``` --- ### 高效实现方案(边界收缩法) ```java import java.util.ArrayList; import java.util.List; class Solution { public List<Integer> spiralOrder(int[][] matrix) { List<Integer> result = new ArrayList<>(); if (matrix == null || matrix.length == 0) return result; int top = 0, bottom = matrix.length - 1; int left = 0, right = matrix[0].length - 1; while (top <= bottom && left <= right) { // 1. 从左到右遍历顶层 for (int j = left; j <= right; j++) { result.add(matrix[top][j]); } top++; // 2. 从上到下遍历右侧 for (int i = top; i <= bottom; i++) { result.add(matrix[i][right]); } right--; // 3. 检查是否仍有行需要处理 if (top <= bottom) { // 从右到左遍历底层 for (int j = right; j >= left; j--) { result.add(matrix[bottom][j]); } bottom--; } // 4. 检查是否仍有列需要处理 if (left <= right) { // 从下到上遍历左侧 for (int i = bottom; i >= top; i--) { result.add(matrix[i][left]); } left++; } } return result; } } ``` --- ### 算法解析 1. **边界初始化**: - `top=0`, `bottom=行数-1` - `left=0`, `right=列数-1` 2. **四步循环**: ```java while (top <= bottom && left <= right) { // 向右遍历 → [top行, left→right] // 向下遍历 ↓ [right列, top→bottom] // 向左遍历 ← [bottom行, right→left] (需检查top<=bottom) // 向上遍历 ↑ [left列, bottom→top] (需检查left<=right) } ``` 3. **边界收缩**: - 每完成一个方向遍历后收缩对应边界 - 例如:完成顶层遍历后 `top++` 4. **条件检查**: - 向左/向上遍历前需检查边界有效性 - 防止单行/单列情况下的重复遍历[^1] --- ### 时间复杂度分析 - **时间复杂度**:$O(m \times n)$ 需访问矩阵中的每个元素恰好一次 - **空间复杂度**:$O(1)$(不考虑输出列表) 仅使用固定数量的指针变量 --- ### 测试用例 ```java public static void main(String[] args) { Solution solution = new Solution(); // 示例测试 int[][] matrix1 = {{1,2,3},{4,5,6},{7,8,9}}; System.out.println(solution.spiralOrder(matrix1)); // 输出: [1,2,3,6,9,8,7,4,5] int[][] matrix2 = {{1,2,3,4},{5,6,7,8},{9,10,11,12}}; System.out.println(solution.spiralOrder(matrix2)); // 输出: [1,2,3,4,8,12,11,10,9,5,6,7] // 边界测试 int[][] matrix3 = {{7}}; System.out.println(solution.spiralOrder(matrix3)); // 输出: [7] } ``` --- ### 应用场景 1. **图像处理**:像素矩阵的螺旋遍历 2. **游戏开发**:地图探索路径规划 3. **数据压缩**:矩阵数据的螺旋编码 4. **内存管理**:二维存储结构的访问优化[^3] --- ### 相关问题 1. 如何实现**逆时针**螺旋遍历矩阵? 2. 如何处理**非矩形**(如三角形)矩阵的螺旋遍历? 3. 如何将螺旋遍历算法扩展**三维矩阵**? 4. 在图像处理中,螺旋遍历如何优化**局部性原理**? 5. 如何修改算法实现**从外向内**和**从内向外**两种螺旋顺序?[^2]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值