It is a recursion. Deal with one row and one column at a time.

```
public class Solution {
public List<Integer> spiralOrder(int[][] matrix) {
List<Integer> ans = new LinkedList<>();
int m = matrix.length, n = m > 0 ? matrix[0].length : 0;
rec(matrix, 0, m, 0, n, 1, ans);
return ans;
}
private void rec(int[][] matrix, int roHead, int roTail, int coHead, int coTail, int k, List<Integer> ans) {
if (roHead == roTail || coHead == coTail) return;
for (int i = roHead, j = coHead; j != coTail; j += k) ans.add(matrix[i][j]);
for (int i = roHead +k, j = coTail - k; i != roTail; i += k) ans.add(matrix[i][j]);
rec(matrix, roTail - k, roHead, coTail - 2*k, coHead - k, -k, ans);
}
}
```