给你一个 m x n 的字符矩阵 box ,它表示一个箱子的侧视图。箱子的每一个格子可能为:
- '#' 表示石头
- '*' 表示固定的障碍物
- '.' 表示空位置
这个箱子被 顺时针旋转 90 度 ,由于重力原因,部分石头的位置会发生改变。每个石头会垂直掉落,直到它遇到障碍物,另一个石头或者箱子的底部。重力 不会 影响障碍物的位置,同时箱子旋转不会产生惯性 ,也就是说石头的水平位置不会发生改变。 题目保证初始时 box 中的石头要么在一个障碍物上,要么在另一个石头上,要么在箱子的底部。 请你返回一个_ _n x m的矩阵,表示按照上述旋转后,箱子内的结果。
先将数组旋转 90 度,获得新数组,再进行后续处理。
int m = box.length; // 1
int n = box[0].length; // 3
char[][] res = new char[n][m]; // 3 * 1
for (int row = 0; row < m; row++) {
for (int col = 0; col < n; col++) {
res[col][m - 1 - row] = box[row][col];
}
}
处理数据的过程,每一列从下往上遍历,需要记录当前可能会被放石头的位置,从下往上,
- 如果是石头('#'),就把石头移到记录的位置;
- 如果是障碍物('*'),就更新记录可能会被放石头的位置为它的上一行;
- 如果是空位('.'),不进行处理。
for (int col = 0; col < m; col++) { // 列
int p = n - 1;
for (int row = n - 1; row >= 0; row--) { // 行
switch (res[row][col]) {
case '#':
res[row][col] = '.';
res[p][col] = '#';
p--;
break;
case '*':
p = row - 1;
break;
default:
break;
}
}
}
也可以先处理数据,再旋转
需要注意的地方(没错,就是我写的 bug):
- 旋转 90°,可不是简单把行变成列,它是第一行变成了最后一列,以此类推,最后一行变成第一列。
- 移动石头的过程,需要将原来石头的位置变成空位,不然石头可能会变多哟。
- 上面一点中,至于先移石头还是先变空位,需要注意先后关系,每一列最后一个位置和障碍物上一行时,石头的位置可能没发生变化,后变空位石头就会变少。
完整代码:
class Solution {
public char[][] rotateTheBox(char[][] box) {
int m = box.length; // 1
int n = box[0].length; // 3
char[][] res = new char[n][m]; // 3 * 1
for (int row = 0; row < m; row++) {
for (int col = 0; col < n; col++) {
res[col][m - 1 - row] = box[row][col];
}
}
for (int col = 0; col < m; col++) { // 列
int p = n - 1;
for (int row = n - 1; row >= 0; row--) { // 行
switch (res[row][col]) {
case '#':
if (p != row) {
res[row][col] = '.';
res[p][col] = '#';
}
p--;
break;
case '*':
p = row - 1;
break;
default:
break;
}
}
}
return res;
}
}
后记:
-
switch 支持的数据类型
- 基本数据类型:char,byte,short,int
- 包装数据类型:Character,Byte,Short,Integer
- 枚举类型:Enum
- 字符串类型:String(JDK 7+ 开始支持)
-
多分支 if 和 switch 的选择
- switch 支持的数据类型的限制
- 代码简洁性
- switch 只能用于等于,if 范围更广
- switch 中不使用 break,可一直执行
- case 值判断方式,效率更高