这个题目刚开始看其实感觉是有点麻烦的,就真的模仿了那种螺旋的思路走完一圈然后从某个地方再进去…。后来捋了一下思路,其实完全可以把它当做是一个一个的环。我们每次遍历都是在遍历一个环,然后再依次遍历下一个环。那么问题就变得简单了,只需要知道我们遍历一个环的时候需要哪些数据就行了。我们只需要两类数据:
- 一个环的左上角坐标
- 一个环的长度和宽度
有了这两类值,我们只需要不断地进行它们,就能不断地遍历一个个的环。
当然遍历环也比较简单,也就是从左上角开始不停地变化坐标就行。但是要注意的是,遍历环的时候如果遇到只有一行或者只有一列的情况,可能会添加重复的元素。虽然我写的时候感觉逻辑上一点问题没有(就是当做一个环来遍历),但是测试用例的第二个总是会多加一个6。当然那我知道是哪一行导致的,但是还是不太明白很通用的解决办法,所以只能是把这种只有一行或一列的环单独拿出来考虑。直接上代码:
public List<Integer> spiralOrder(int[][] matrix) {
List<Integer> result = new LinkedList<>();
if (matrix.length == 0)
return result;
int x = 0, y = 0, chang = matrix[0].length, kuan = matrix.length;
while (chang > 0 && kuan > 0) { //要保证环的长度和宽度大于0(有元素)
List<Integer> temp = helper(matrix, x++, y++, chang, kuan);
chang -= 2; //没进入一个新环时,长、宽都要减去2
kuan -= 2;
result.addAll(temp);
}
return result;
}
//得到一个环的所有元素,参数为环左上角元素的坐标以及环的长度、宽度
private List<Integer> helper(int[][] matrix, int x, int y, int chang, int kuan) {
List<Integer> result = new LinkedList<>();
int startX = x, startY = y;
if (chang == 1) { //只有一列
for (; x < startX + kuan; ++x)
result.add(matrix[x][y]);
return result;
} else if (kuan == 1) { //只有一行
for (; y < startY + chang; ++y)
result.add(matrix[x][y]);
return result;
}
for (; y < startY + chang; ++y)
result.add(matrix[x][y]);
--y;
for (++x; x < startX + kuan; ++x)
result.add(matrix[x][y]);
--x;
for (--y; y >= startY; --y)
result.add(matrix[x][y]);
++y;
for (--x; x > startX; --x)
result.add(matrix[x][y]);
return result;
}