Spiral Matrix 输出旋转矩阵@LeetCode

又是一道关于旋转矩阵的问题,思路都很固定,但具体写的时候很容易出错



package Level4;

import java.util.ArrayList;

/**
 * Spiral Matrix
 * 
 * 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].

Discuss


 * 
 */
public class S54 {

	public static void main(String[] args) {
//		int[][] matrix = {{1,2,3,4,5},
//								{14,15,16,17,6},
//								{13,20,19,18,7},
//								{12,11,10,9,8}};
		int[][] matrix = {{1,2,3,4},
								{5,6,7,8},
								{9,10,11,12}};
//		int[][] matrix = {{1,2,3}};
		System.out.println(spiralOrder(matrix));
	}

	public static ArrayList<Integer> spiralOrder(int[][] matrix) {
		ArrayList<Integer> ret = new ArrayList<Integer>();
		if(matrix.length == 0){
			return ret;
		}
		int m = matrix.length;
		int n = matrix[0].length;
		int margin = 1;
//		rec(matrix, m, n, margin, 0, 0, ret);
		
		rec2(matrix, m, n, 0, ret);
		return ret;
	}

	/* 
	              n
	     ______________(x,y+n-1)
	    |(x,y)               |  
	    |                      |  m
	    |_____________ |
	    (x+m-1,y)          (x+m-1,y+n-1)
	    
	    m: 矩阵高度
	 	n: 矩阵宽度
	 	margin: 每次变化后减少量,此题固定为1
	 	x,y: 左上角坐标
	 	可以推出,右上角坐标为(y+n)
	*/
	public static void rec(int[][] matrix, int m, int n, int margin, int x, int y, ArrayList<Integer> ret){
		if(m<=0 || n<=0){
			return;
		}
		
		if(m==1 && n==1){				// 只包含一个元素的情况
			ret.add(matrix[x][y]);
			return;
		}else if(m==1 && n!=1){		// 只有一行的情况
			for(int j=y; j<y+n; j++){
				ret.add(matrix[y][j]);
			}
			return;
		}else if(m!=1 && n==1){		// 只有一列的情况
			for(int i=x; i<x+m; i++){
				ret.add(matrix[i][x]);
			}
			return;
		}
		
		// 以下是有多行多列的情况
		for(int i=y; i<y+n-margin; i++){		// 向右
			ret.add(matrix[x][i]);
		}
		for(int i=x; i<x+m-margin; i++){		// 向下
			ret.add(matrix[i][y+n-margin]);
		}
		for(int i=y+n-margin; i>x; i--){		// 向左
			ret.add(matrix[x+m-margin][i]);
		}
		for(int i=x+m-margin; i>x; i--){		// 向上
			ret.add(matrix[i][y]);
		}
		rec(matrix, m-2, n-2, margin, x+1, y+1, ret);		// 改变长宽度和初始点位置
	}
	
	
	// http://leetcode.com/2010/05/printing-matrix-in-spiral-order.html
	// m: 行数 n:列数 k:第几层
	public static void rec2(int[][] matrix, int m, int n, int k, ArrayList<Integer> ret){
		if(m<=0 || n<=0){
			return;
		}
		if(m == 1){			// 只有一行时
			for(int j=0; j<n; j++){
				ret.add(matrix[k][k+j]);
			}
			return;
		}
		if(n == 1){			// 只有一列时
			for(int i=0; i<m; i++){
				ret.add(matrix[k+i][k]);
			}
			return;
		}
		
		for(int j=0; j<n-1; j++){		// 从左上第一个到右上倒二个
			ret.add(matrix[k][k+j]);
		}
		for(int i=0; i<m-1; i++){		// 从右上第一个到右下倒二个
			ret.add(matrix[k+i][k+n-1]);
		}
		for(int j=0; j<n-1; j++){		// 从右下第一个到左下倒二个
			ret.add(matrix[k+m-1][k+n-1-j]);
		}
		for(int i=0; i<m-1; i++){		// 从左下第一个到左上倒二个
			ret.add(matrix[k+m-1-i][k]);
		}
		rec2(matrix, m-2, n-2, k+1, ret);		// 剩下m-2行和n-2列,k+1 level
	}
}



终于找到一种不容易写错的方法,要点就是在定义递归时用(x1,y1), (x2,y2)来限制当前考虑矩阵的左上角和右下角。这样就能方便非常多。但要保证左上角的位置必须小于右下角的位置!

public class Solution {
    public static List<Integer> spiralOrder(int[][] matrix) {
        List<Integer> ret = new ArrayList<Integer>();
        if(matrix.length == 0) {
        	return ret;
        }
        rec(matrix, ret, 0, 0, matrix.length-1, matrix[0].length-1);
        return ret;
    }
    
    public static void rec(int[][] matrix, List<Integer> ret, int x1, int y1, int x2, int y2) {
    	int m = x2 - x1 + 1;
    	if(x1 > x2 || y1 > y2) {  // (x1,y1) must be smaller than (x2,y2)
    		return;
    	}
        if(m <= 0) {        // empty
            return;
        }
        if(m == 1) {        // single row
            for(int j=y1; j<=y2; j++) {
                ret.add(matrix[x1][j]);
            }
            return;
        }
        int n = y2 - y1 + 1;
        if(n == 1) {        // single column
        	for(int i=x1; i<=x2; i++) {
                ret.add(matrix[i][y1]);
            }
            return;
        }
        for(int j=y1; j<y2; j++) {
            ret.add(matrix[x1][j]);
        }
        for(int i=x1; i<x2; i++) {
            ret.add(matrix[i][y2]);
        }
        for(int j=y2; j>y1; j--) {
            ret.add(matrix[x2][j]);
        }
        for(int i=x2; i>x1; i--) {
            ret.add(matrix[i][y1]);
        }
        
        rec(matrix, ret, x1+1, y1+1, x2-1, y2-1);   // shrink boundary
    }
}






评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值