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.
Example 1:
Input: boxGrid = [["#",".","#"]] Output: [["."], ["#"], ["#"]]
Example 2:
Input: boxGrid = [["#",".","*","."], ["#","#","*","."]] Output: [["#","."], ["#","#"], ["*","*"], [".","."]]
Example 3:
Input: boxGrid = [["#","#","*",".","*","."], ["#","#","#","*",".","."], ["#","#","#",".","#","."]] Output: [[".","#","#"], [".","#","#"], ["#","#","*"], ["#","*","."], ["#",".","*"], ["#",".","."]]
Constraints:
m == boxGrid.length
n == boxGrid[i].length
1 <= m, n <= 500
boxGrid[i][j]
is either '#'
, '*'
, or '.'
.When you get asked this question in a real-life environment, it will often be ambiguous (especially at FAANG). Make sure to ask these questions in that case:
Imagine tilting a box filled with items so that everything falls to one side. The brute force strategy simulates every possible tilt angle, even slightly, and checks the resulting arrangement of items for each angle. It's like physically trying out every angle and observing the result.
Here's how the algorithm would work step-by-step:
def rotate_the_box_brute_force(box):
height = len(box)
width = len(box[0])
best_arrangement = [row[:] for row in box]
# Simulate tilting at different angles (simplified to just one tilt)
for tilt_angle in [1]:
current_arrangement = [row[:] for row in box]
# Simulate the effect of gravity, moving objects down
for column_index in range(width):
for row_index in range(height - 1, -1, -1):
if current_arrangement[row_index][column_index] == '.':
#Find stone above and move it to empty spot
for above_row_index in range(row_index - 1, -1, -1):
if current_arrangement[above_row_index][column_index] == '*':
break
elif current_arrangement[above_row_index][column_index] == '#':
continue
elif current_arrangement[above_row_index][column_index] == '.':
continue
else:
# Move the stone
current_arrangement[row_index][column_index] = '*'
current_arrangement[above_row_index][column_index] = '.'
break
# This is where best arrangement is chosen, choosing first
best_arrangement = current_arrangement
return best_arrangement
Imagine tipping the box onto its side. The key idea is to move each stone as far to the right as possible within its row, only stopping when it hits an obstacle like another stone or the side of the box. We handle this row by row, from top to bottom.
Here's how the algorithm would work step-by-step:
def rotate_the_box(box):
number_of_rows = len(box)
number_of_columns = len(box[0])
rotated_box = [['' for _ in range(number_of_rows)] for _ in range(number_of_columns)]
for row_index in range(number_of_rows):
stone_position = number_of_columns - 1
for column_index in range(number_of_columns - 1, -1, -1):
if box[row_index][column_index] == '#':
box[row_index][column_index] = '.'
box[row_index][stone_position] = '#'
#Find the next possible stone position
stone_position -= 1
elif box[row_index][column_index] == '*':
stone_position = column_index - 1
for row_index in range(number_of_rows):
for column_index in range(number_of_columns):
# Transpose the box to simulate rotation
rotated_box[column_index][number_of_rows - 1 - row_index] = box[row_index][column_index]
return rotated_box
Case | How to Handle |
---|---|
Null or empty input box | Return an empty 2D array or null to indicate invalid input, after checking for null input. |
Box with zero rows or zero columns | Return an empty 2D array as there's nothing to rotate or simulate. |
Box with only one row or one column | Handle rotation and gravity correctly on this simplified box. |
Box containing only obstacles ('*') | Rotate the box as normal; no stones need to fall, so just perform the rotation. |
Box containing only empty cells ('.') | Rotate the box as normal; no stones need to fall, so just perform the rotation. |
Box containing only stones ('#') | Rotate the box, all stones should fall to the 'bottom' edge after rotation. |
Box with stones already at the 'bottom' in some columns, with obstacles above them | Ensure stones don't 'fall' through obstacles and the existing 'bottom' stones are not affected. |
Large box with many rows and columns (scalability) | Ensure the rotation and stone falling algorithm is efficient (e.g., doesn't use excessively nested loops) to avoid time limit issues. |