Given a matrix of m x n elements (m rows, n columns), return all elements of the matrix in spiral order.
给定一个包含 m x n
个元素的矩阵(m 行, n 列),请按照顺时针螺旋顺序,返回矩阵中的所有元素。
Example 1:
Input:
[
[ 1, 2, 3 ],
[ 4, 5, 6 ],
[ 7, 8, 9 ]
]
Output: [1,2,3,6,9,8,7,4,5]
Example 2:
Input:
[
[1, 2, 3, 4],
[5, 6, 7, 8],
[9,10,11,12]
]
Output: [1,2,3,4,8,12,11,10,9,5,6,7]
2. solution
class Solution {
public List<Integer> spiralOrder(int[][] matrix)
{
List ans = new ArrayList();
if (matrix.length == 0) return ans;
int m = matrix.length;
int n = matrix[0].length;
// 定义一个记录访问情况数组matrix2, 0代表未访问,1代表已访问
int [][]matrix2 = new int[m][n];
for(int i=0;i<m;i++)
{
for(int j=0;j<n;j++)
{
matrix2[i][j] = 0;
}
}
// 总共要输出sum = m*n
int num = 1,sum =m*n;
int i=0,j=0;
//action 4个值代表4个动作
//0:right 1:dowm 2:left 3:up
int action = 0;
// 碰壁时移动行为只有4种情况
int[] i_action = {1, -1, -1, 1};
int[] j_action = {-1, -1, 1, 1};
while(num <= sum)
{
// 如果该位置正确,且没有被访问到
if( 0<=i && i<m && 0<=j && j<n && matrix2[i][j]==0)
{
// 输出,并把matrix2标记为已访问
System.out.print(matrix[i][j]);
matrix2[i][j]=1;
// 计数加1
num++;
ans.add(matrix[i][j]);
// 根据相应action改变位置
switch (action)
{
case 0:
j++;
break;
case 1:
i++;
break;
case 2:
j--;
break;
default:
i--;
break;
}
}
// 碰壁时的面对的4个情形是循环出现的,可以用一个长度为4的数组存储解决方案,根据action的值来决定采用哪个方案
else
{
i += i_action[action];
j += j_action[action];
// 碰壁:更新移动方向
action = (action+1)%4;
}
}
return ans;
}
}
When traversing the matrix in the spiral order, at any time we follow one out of the following four directions: RIGHT DOWN LEFT UP. Suppose we are working on a 5 x 3 matrix as such:
0 1 2 3 4 5
6 7 8 9 10
11 12 13 14 15
Imagine a cursor starts off at (0, -1), i.e. the position at ‘0’, then we can achieve the spiral order by doing the following:
- Go right 5 times
- Go down 2 times
- Go left 4 times
- Go up 1 times.
- Go right 3 times
- Go down 0 times -> quit
Notice that the directions we choose always follow the order ‘right->down->left->up’, and for horizontal movements, the number of shifts follows:{5, 4, 3}, and vertical movements follows {2, 1, 0}.
Thus, we can make use of a direction matrix that records the offset for all directions, then an array of two elements that stores the number of shifts for horizontal and vertical movements, respectively. This way, we really just need one for loop instead of four.
Another good thing about this implementation is that: If later we decided to do spiral traversal on a different direction (e.g. Counterclockwise), then we only need to change the Direction matrix; the main loop does not need to be touched.
vector<int> spiralOrder(vector<vector<int>>& matrix) {
vector<vector<int> > dirs{{0, 1}, {1, 0}, {0, -1}, {-1, 0}};
vector<int> res;
int nr = matrix.size(); if (nr == 0) return res;
int nc = matrix[0].size(); if (nc == 0) return res;
vector<int> nSteps{nc, nr-1};
int iDir = 0; // index of direction.
int ir = 0, ic = -1; // initial position
while (nSteps[iDir%2]) {
for (int i = 0; i < nSteps[iDir%2]; ++i) {
ir += dirs[iDir][0]; ic += dirs[iDir][1];
res.push_back(matrix[ir][ic]);
}
nSteps[iDir%2]--;
iDir = (iDir + 1) % 4;
}
return res;
}