You are given an m x n
matrix of characters boxGrid
representing a side-view of a box. Each cell of the box is one of the following:
#
*
.
The box is rotated 90 degrees clockwise, causing some of the stones to fall due to gravity. Each stone falls down until it lands on an obstacle, another stone, or the bottom of the box. Gravity does not affect the obstacles' positions, and the inertia from the box's rotation does not affect the stones' horizontal positions.
It is guaranteed that each stone in boxGrid
rests on an obstacle, another stone, or the bottom of the box.
Return an n x m
matrix representing the box after the rotation described above.
For example:
Example 1:
Input:
boxGrid = [["#",".","#"]]
Output:
[["."],
["#"],
["#"]]
Example 2:
Input:
boxGrid = [["#",".","*","."],
["#","#","*","."]]
Output:
[["#","."],
["#","#"],
["*","*"],
[".","."]]
How would you approach this problem and what is the time and space complexity of your solution?
The naive approach involves first rotating the box 90 degrees clockwise and then simulating the falling of the stones. Rotating the box can be done by creating a new matrix and filling it with the appropriate values from the original matrix. Simulating the falling of the stones involves iterating through each column from bottom to top. If we encounter a stone, we move it down as far as it can go until it hits an obstacle, another stone, or the bottom of the box.
class Solution {
public char[][] rotateTheBox(char[][] box) {
int m = box.length;
int n = box[0].length;
char[][] rotatedBox = new char[n][m];
// Rotate the box
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
rotatedBox[j][m - 1 - i] = box[i][j];
}
}
// Simulate the falling of stones
for (int j = 0; j < n; j++) {
for (int i = m - 1; i >= 0; i--) {
if (rotatedBox[j][i] == '#') {
int k = i + 1;
while (k < m && rotatedBox[j][k] == '.') {
k++;
}
rotatedBox[j][i] = '.';
rotatedBox[j][k - 1] = '#';
}
}
}
return rotatedBox;
}
}
Therefore, the overall runtime is O(m * n * m).
Thus, the overall space usage is O(m * n).
The optimal solution reduces the time complexity of simulating the falling of the stones. Instead of moving one stone at a time, we can count the number of stones between obstacles. Then, fill the section with the appropriate number of stones and empty cells.
class Solution {
public char[][] rotateTheBox(char[][] box) {
int m = box.length;
int n = box[0].length;
char[][] rotatedBox = new char[n][m];
// Rotate the box
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
rotatedBox[j][m - 1 - i] = box[i][j];
}
}
// Simulate the falling of stones
for (int j = 0; j < n; j++) {
int lastObstacle = m;
int stoneCount = 0;
for (int i = m - 1; i >= -1; i--) {
if (i == -1 || rotatedBox[j][i] == '*') {
// Fill the section with stones and empty cells
for (int k = i + 1; k < lastObstacle; k++) {
if (stoneCount > 0) {
rotatedBox[j][k] = '#';
stoneCount--;
} else {
rotatedBox[j][k] = '.';
}
}
if (i != -1) {
rotatedBox[j][i] = '*'; // Keep the obstacle
}
lastObstacle = i;
} else if (rotatedBox[j][i] == '#') {
stoneCount++;
rotatedBox[j][i] = '.'; // Clear the original stone position
}
}
}
return rotatedBox;
}
}
Therefore, the overall runtime is O(m * n).
Thus, the overall space usage is O(m * n).