螺旋矩阵(Java)

给定一个包含 m x n 个元素的矩阵(m 行, n 列),请按照顺时针螺旋顺序,返回矩阵中的所有元素。

示例 1:

输入:
[
 [ 1, 2, 3 ],
 [ 4, 5, 6 ],
 [ 7, 8, 9 ]
]
输出: [1,2,3,6,9,8,7,4,5]

示例 2:

输入:
[
  [1, 2, 3, 4],
  [5, 6, 7, 8],
  [9,10,11,12]
]
输出: [1,2,3,4,8,12,11,10,9,5,6,7]

思路1:模拟

绘制螺旋轨迹路径,我们发现当路径超出界限或者进入之前访问过的单元格时,会顺时针旋转方向。

算法

假设数组有R行C列,seen[r][c] 表示第 r 行第 c 列的单元格之前已经被访问过了。当前所在位置为(r, c),前进方向是di。我们希望访问所有 R x C 个单元格。

当我们遍历整个矩阵,下一步候选移动位置是(cr, cc)。如果这个候选位置在矩阵范围内并且没有被访问过,那么它将会变成下一步移动的位置;否则,我们将前进方向顺时针旋转之后再计算下一步的移动位置。

题解:

class Solution1{
	public List<Integer>spiralOrder(int[][] matrix){
		//定义一个链表
		List ans = new ArrayList();
		//矩阵为空则返回空链表
		if(matrix.length == 0)
			return ans;
		//获取矩阵维度
		int R = matrix.length, C = matrix[0].length;
		//定义同样维度的布尔型矩阵,用于标识矩阵元素是否被访问过
		boolean[][] seen = new boolean[R][C];
		//
		int[] dr = {0,1,0,-1};
		int[] dc = {1,0,-1,0};
		//前进方向di,当前所在位置[r][c]
		int r = 0,c = 0,di = 0;
		//
		for(int i=0;i<R*C;i++) {
			ans.add(matrix[r][c]);
			//矩阵中访问的元素位置标为true
			seen[r][c] = true;
			//候选移动位置是 (cr, cc)
			int cr = r + dr[di];
			int cc = c + dc[di];        //boolean类型定义的数组,默认值是false
			if(cr >= 0 && cr < R && cc >= 0 && cc < C && !seen[cr][cc]){
				r = cr;          //if括号内,当且仅当不超出边界且未被访问过才为真
				c = cc;
			}else { 
                     //如果候选移动位置超出边界或被访问过,则顺时针旋转方向 
				di = (di + 1) % 4;
				r += dr[di];
				c += dc[di];
			}
		}
		return ans;
	}
}

复杂度分析

时间复杂度: O(N),其中 N 是输入矩阵所有元素的个数。因为我们将矩阵中的每个元素都添加进答案里。
空间复杂度: O(N),需要两个矩阵 seen 和 ans 存储所需信息。

思路2:按层模拟

答案是最外层所有元素按照顺时针顺序输出,其次是次外层,以此类推。

对于每层,我们从左上方开始以顺时针的顺序遍历所有元素,假设当前层左上角坐标是(r1, c1),右下角坐标是(r2, c2)。

首先,遍历上方的所有元素(r1, c),按照 c = c1,...,c2 的顺序。然后遍历右侧的所有元素(r, c2),按照 r = r1+1,...,r2 的顺序。如果这一层有四条边(也就是r1 < r2 并且c1 < c2 ),我们以下图所示的方式遍历下方的元素和左侧的元素。

class Solution2{
		public List<Integer>spiralOrder(int[][] matrix){
			List ans = new ArrayList();
			if(matrix.length == 0)
				return ans;
			int r1 = 0,r2 = matrix.length - 1;
			int c1 = 0,c2 = matrix[0].length - 1;
			while(r1 <= r2 && c1 <= c2) {
				for(int c = c1; c <= c2; c++)
					ans.add(matrix[r1][c]);
				for(int r = r1 + 1; r <= r2 ;r++)
					ans.add(matrix[r][c2]);
				if(r1 < r2 && c1 < c2) {
					for(int c = c2 - 1;c > c1;c--)
						ans.add(matrix[r2][c]);
					for(int r = r2;r > r1;r--)
						ans.add(matrix[r][c1]);
				}
				r1++;
				r2--;
				c1++;
				c2--;
			}
			return ans;
		}
}

复杂度分析

时间复杂度: O(N),其中 N 是输入矩阵所有元素的个数。因为我们将矩阵中的每个元素都添加进答案里。
空间复杂度: O(N),需要矩阵 ans 存储信息。

(本人倾向于第一种)

来源:https://leetcode-cn.com/problems/spiral-matrix/

猜你喜欢

转载自blog.csdn.net/qq_41904729/article/details/104108429