旋转遍历矩阵 Spiral Matrix

本文介绍了一种螺旋遍历矩阵的算法实现,并提供了三种不同的解决方案。包括直接按螺旋顺序遍历、利用边界变量进行控制以及使用方向数组实现迭代。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

问题:

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].

解决:

① 没有特别简化的方法,只能一步步的来。如果矩阵只有一行或者一列,那么无需转圈,依次输出即可。其他情况均需转圈:从左到右,从上到下,从右到左,从下到上。 从大圈依次循环到小圈即可。

class Solution { //3ms
    public List<Integer> spiralOrder(int[][] matrix) {
        List<Integer> res = new ArrayList<>();
        if(matrix == null || matrix.length == 0 || matrix[0].length == 0) return res;
        getSpiral(matrix,0,0,matrix.length,matrix[0].length,res);
        return res;
    }
    public void getSpiral(int[][] matrix,int x,int y,int rows,int cols,List<Integer> res){
        if(rows <= 0 || cols <= 0) return;
        for (int i = 0;i < cols ;i ++ ) {//由左到右
            res.add(matrix[x][y + i]);
        }
        for (int i = 1;i < rows - 1 ;i ++ ) {//由上到下
            res.add(matrix[x + i][y + cols - 1]);
        }
        if(rows > 1){//由右到左
            for (int i = cols - 1;i >= 0 ;i -- ) {
                res.add(matrix[x + rows - 1][y + i]);
            }
        }
        if(cols > 1){
            for (int i = rows - 2;i > 0 ;i -- ) {//由下到上
                res.add(matrix[x + i][y]);
            }
        }
        getSpiral(matrix,x + 1,y + 1,rows - 2,cols - 2,res);
    }
}

② 使用top,bottom,right,left记录四个角。可以减少错误。只需要判断四个边界是否相撞即可

class Solution{ //3ms
    public List<Integer> spiralOrder(int[][] matrix) {
        List<Integer> res = new ArrayList<Integer>();
        if (matrix == null || matrix.length == 0 || matrix[0].length == 0) {
            return res;
        }
        int rows = matrix.length;
        int cols = matrix[0].length;
        int left = 0;
        int right = cols - 1;
        int top = 0;
        int bottom = rows - 1;
        while (left <= right && top <= bottom) {
            for (int i = left; i <= right; i ++) {
                res.add(matrix[top][i]);
            }
            for (int i = top + 1; i <= bottom - 1; i ++) {
                res.add(matrix[i][right]);
            }
            if (top != bottom) {
                for (int i = right; i >= left; i --) {
                    res.add(matrix[bottom][i]);
                }    
            }
            if (left != right) {
                for (int i = bottom - 1; i >= top + 1; i --) {
                    res.add(matrix[i][left]);
                }    
            }
            left ++;
            right --;
            top ++;
            bottom --;
        }
        return res;
    }
}

③ 在discuss中看到以下方法:用Iterator来实现,记录2个方向数组,分别表示在x方向,y方向的前进方向。1表示右或是下,-1表示左或是向上,0表示不动作。

// 1: means we are visiting the row by the right direction.
// -1: means we are visiting the row by the left direction.
int[] x = {1, 0, -1, 0};    
// 1: means we are visiting the colum by the down direction.
// -1: means we are visiting the colum by the up direction.
int[] y = {0, 1, 0, -1};
这种方向矩阵将会很常用在各种旋转数组上。。。。。。

class Solution{ //2ms
    public List<Integer> spiralOrder(int[][] matrix) {
        List<Integer> res = new ArrayList<Integer>();
        int rows = matrix.length;
        int cols = matrix[0].length;  
        if (matrix == null || rows == 0 || cols == 0) {
            return res;   
        }          
        int visitedRows = 0;//已经遍历过的行
        int visitedCols = 0;
        int[] x = {1, 0, -1, 0};
        int[] y = {0, 1, 0, -1};
        // 0: right, 1: down, 2: left, 3: up.
        int direct = 0;  //方向矩阵的下标
        int startx = 0;//记录当前遍历到的横坐标
        int starty = 0;
        int candidateNum = 0;//记录需要遍历的行数或列数
        int step = 0;//记录当前行或列已经遍历过的个数

        while (true) {
            if (x[direct] == 0) {
                //遍历y轴方向.
                candidateNum = rows - visitedRows;
            } else {
                // 遍历x轴方向                                                                                                                                         candidateNum = cols - visitedCols;
            }
            if (candidateNum <= 0) {
                break;
            }
            res.add(matrix[startx][starty]);
            step ++;
            if (step == candidateNum) {
                step = 0;
                visitedRows += x[direct] == 0 ? 0: 1;
                visitedCols += y[direct] == 0 ? 0: 1;            
                // move forward the direction.
                direct ++;
                direct = direct % 4;
            }        
            // 根据方向来移动横坐标和纵坐标。
            startx += y[direct];
            starty += x[direct];
        }
        return res;
    }
}

转载于:https://my.oschina.net/liyurong/blog/1529392

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值