leetcode 54. Spiral Matrix

257 篇文章 17 订阅

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

题意就是螺旋式地输出一个数组。注意行数有 m 行,列数有 n 列,并不是正方形。

我的思路是找到其中的规律,总是按照 往右走->往下走->往左走->往上走 这样子循环往复的,而在水平方向走时,比如一开始往右走了3步,接下来水平方向往左走只能走2步(因为被往下走的那段占了),再之后往右走只能走1步。所以说 每往水平方向走一趟,能走的步数都要减一。竖直方向也是同理。

需要注意的是,水平方向初始能走的步数是列数,竖直方向能走的步数是行数。此外,刚开始的坐标位置应置于 (-1,0),因为一开始需要往右走 n 个格子(是先加方向再add list)。

另外,当任意一个方向上能走的步数变为 0 时,此时跳出while循环,还需要再按照下一个方向走一回,因为有可能另外一个方向上还没走完(详情见我的测试用例)。

package leetcode;

import java.util.ArrayList;
import java.util.List;

public class Spiral_Matrix_54 {

	public List<Integer> spiralOrder(int[][] matrix) {
		List<Integer> list = new ArrayList<Integer>();
		if(matrix.length==0||matrix[0].length==0){
			return list;
		}
		int[][] direction = new int[][] { { 0, 1 }, { 1, 0 }, { 0, -1 }, { -1, 0 }// 右下左上
		};
		int m=matrix.length;
		int n=matrix[0].length;
		int dPointer=0;
		int x=0;
		int y=-1;
		m--;
		while(m!=0&&n!=0){
			if(dPointer%2==0){//横着走,走的是列数
				for(int i=0;i<n;i++){
					x=x+direction[dPointer][0];
					y=y+direction[dPointer][1];
					list.add(matrix[x][y]);
				}
				n--;
			}
			else{//竖着走,走的是行数
				for(int i=0;i<m;i++){
					x=x+direction[dPointer][0];
					y=y+direction[dPointer][1];
					list.add(matrix[x][y]);
				}
				m--;				
			}
			dPointer=(dPointer+1)%4;
		}
		if(dPointer%2==0){//横着走,走的是列数
			for(int i=0;i<n;i++){
				x=x+direction[dPointer][0];
				y=y+direction[dPointer][1];
				list.add(matrix[x][y]);
			}
		}
		else{//竖着走,走的是行数
			for(int i=0;i<m;i++){
				x=x+direction[dPointer][0];
				y=y+direction[dPointer][1];
				list.add(matrix[x][y]);
			}				
		}
		return list;
	}

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Spiral_Matrix_54 s=new Spiral_Matrix_54();
		int[][] matrix=new int[][]{
			{1,2,3,4,5},
			{6,7,8,9,10},
			{11,12,13,14,15}
		};
		List<Integer> list=s.spiralOrder(matrix);
		for(int i:list){
			System.out.print(i+" ");
		}
		System.out.println();
	}

}
我的代码真是冗长啊。我发现可以优化我的代码,把while循环的判断条件改一下,使用一个计数器,来统计是否已经 add 了 m*n 个数,当个数达到 m*n 时,跳出循环。这样就不需要在 while 循环之后再走一遍方向了。

相比之下大神的解法就很机智。

先是往右走,并增加 rowBegin, 然后往下走并减小 colEnd, 之后往左走并减小 rowEnd, 最后往上走并增加 colBegin。需要注意的是,当往左走和往上走时,需要检查是否 rowBegin <= rowEnd 和 colBegin <= colEnd,以防止重复。

相当于每走完一边,就在那一边筑一堵墙。比如往右走,也就是在上边界走,走完后在上边界筑墙,即 rowBegin++。

public class Solution {
    public List<Integer> spiralOrder(int[][] matrix) {
        
        List<Integer> res = new ArrayList<Integer>();
        
        if (matrix.length == 0) {
            return res;
        }
        
        int rowBegin = 0;
        int rowEnd = matrix.length-1;
        int colBegin = 0;
        int colEnd = matrix[0].length - 1;
        
        while (rowBegin <= rowEnd && colBegin <= colEnd) {
            // Traverse Right
            for (int j = colBegin; j <= colEnd; j ++) {
                res.add(matrix[rowBegin][j]);
            }
            rowBegin++;
            
            // Traverse Down
            for (int j = rowBegin; j <= rowEnd; j ++) {
                res.add(matrix[j][colEnd]);
            }
            colEnd--;
            
            if (rowBegin <= rowEnd) {
                // Traverse Left
                for (int j = colEnd; j >= colBegin; j --) {
                    res.add(matrix[rowEnd][j]);
                }
            }
            rowEnd--;
            
            if (colBegin <= colEnd) {
                // Traver Up
                for (int j = rowEnd; j >= rowBegin; j --) {
                    res.add(matrix[j][colBegin]);
                }
            }
            colBegin ++;
        }
        
        return res;
    }
}
这道题有solutions:  https://leetcode.com/problems/spiral-matrix/solution/

solutions的解法和大神的解法思路一样,就不赘述了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值