You are controlling a robot that is located somewhere in a room. The room is modeled as a grid of cells, where each cell can be free or blocked.
The robot can move forward, turn left, or turn right. When you command the robot to move forward, it moves one cell in the direction it is facing.
The robot cannot enter blocked cells.
Given the room in a grid format, your task is to clean all the free cells. The robot starts at an unknown location, facing up.
For simplicity, assume:
Interface:
interface Robot {
// returns true if next cell is open and robot moves into the cell.
// returns false if next cell is blocked and robot stays on the current cell.
boolean move();
// Robot will stay on the same cell after calling rotateLeft/rotateRight.
// Each turn will be 90 degrees.
void rotateRight();
void rotateLeft();
// Clean the current cell.
void clean();
}
Example:
Input:
room = [
[1,1,1,1,1,1,1,1],
[1,0,1,1,1,1,1,1],
[1,1,1,0,1,1,1,1],
[1,1,1,1,0,1,1,1],
[1,1,1,1,1,1,1,1]
],
row = 1, col = 3
Explanation:
All grids in the room are marked by either 0 or 1.
0 means the cell is blocked, while 1 means the cell is accessible.
The robot initially starts at the position (1, 3).
From that point, the robot can clean all accessible cells.
Note:
Robot class.room directly.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:
The robot needs to clean every room. The brute force method makes the robot try every possible path, moving forward, turning, and backtracking until it has explored everywhere it can possibly go. It's like trying every single maze solution until one works.
Here's how the algorithm would work step-by-step:
def robot_room_cleaner_brute_force(robot):
visited_cells = set()
current_direction = 0 # 0: up, 1: right, 2: down, 3: left
current_row = 0
current_col = 0
def move_forward():
nonlocal current_row, current_col
if current_direction == 0:
current_row -= 1
elif current_direction == 1:
current_col += 1
elif current_direction == 2:
current_row += 1
else:
current_col -= 1
def move_back():
nonlocal current_row, current_col
if current_direction == 0:
current_row += 1
elif current_direction == 1:
current_col -= 1
elif current_direction == 2:
current_row -= 1
else:
current_col += 1
def get_current_cell():
return (current_row, current_col)
while True:
current_cell = get_current_cell()
if current_cell not in visited_cells:
robot.clean()
visited_cells.add(current_cell)
can_move_forward = robot.move()
if can_move_forward:
move_forward()
continue
else:
# Try all directions by turning right
turned_count = 0
while turned_count < 4:
robot.turn_right()
current_direction = (current_direction + 1) % 4
turned_count += 1
can_move_forward = robot.move()
if can_move_forward:
move_forward()
break
# If we can't move anywhere, backtrack
if turned_count == 4:
move_back()
robot.turn_right()
robot.turn_right()
if not robot.move():
break
move_forward()
robot.turn_right()
robot.turn_right()
all_cleaned = True
for row_delta in range(-10, 11):
for col_delta in range(-10, 11):
test_row = current_row + row_delta
test_col = current_col + col_delta
if (test_row, test_col) not in visited_cells and robot.is_valid_move(row_delta, col_delta):
all_cleaned = False
break
if not all_cleaned:
break
if all_cleaned and not can_move_forward:
break
return list(visited_cells)The problem involves simulating a robot cleaning a room. Instead of exhaustively exploring every possible path, the efficient solution relies on a depth-first search strategy combined with backtracking to systematically explore the room and ensure complete cleaning.
Here's how the algorithm would work step-by-step:
class Robot:
def move(self):
return True
def turn_left(self):
return
def turn_right(self):
return
def clean(self):
return
def clean_room(robot):
visited = set()
# Directions: up, right, down, left
directions = [(-1, 0), (0, 1), (1, 0), (0, -1)]
def go_back():
robot.turn_right()
robot.turn_right()
robot.move()
robot.turn_right()
robot.turn_right()
def explore(row, col, current_direction):
visited.add((row, col))
robot.clean()
for index in range(4):
new_direction = (current_direction + index) % 4
new_row = row + directions[new_direction][0]
new_col = col + directions[new_direction][1]
#Avoid exploring already cleaned or obstacle cells
if (new_row, new_col) not in visited:
robot.turn_right()
if robot.move():
# Explore in the new direction.
explore(new_row, new_col, new_direction)
# Backtrack after exploring the new direction.
go_back()
explore(0, 0, 0)| Case | How to Handle |
|---|---|
| Null or empty room (no cells) | The base case for the recursion should immediately return, avoiding any processing. |
| Room with a single cell | The robot cleans it and returns without any further movements. |
| Room is a straight line (1xn or nx1) | The algorithm should handle this by moving along the line, cleaning each cell, and turning around at the end if necessary. |
| Room is a fully walled-in space (no exits) | The robot might get stuck in the initial cell if it cannot move, requiring a check for this and immediate termination. |
| Robot starts in a dirty cell with no cleanable adjacent cells | The robot cleans the current cell and algorithm will backtrack immediately as there is nowhere else to go. |
| Circular room layout where returning to the starting cell doesn't indicate full exploration | Maintain a set of visited cells to avoid infinite loops and ensure full exploration, regardless of cyclic paths. |
| Integer overflow in distance calculations (if applicable) | Use appropriate data types to prevent overflow (e.g., long) or ensure calculations are done in a way that prevents overflow. |
| Maximum recursion depth exceeded for very large rooms | While unlikely given reasonable room sizes, consider iterative solution instead of recursive or implement tail-call optimization. |