You are given four integers sx, sy, fx, fy, and a non-negative integer t.
In an infinite 2D grid, you start at the cell (sx, sy). Each second, you must move to any of its adjacent cells.
Return true if you can reach cell (fx, fy) after exactly t seconds, or false otherwise.
A cell's adjacent cells are the 8 cells around it that share at least one corner with it. You can visit the same cell several times.
Example 1:
Input: sx = 2, sy = 4, fx = 7, fy = 7, t = 6 Output: true Explanation: Starting at cell (2, 4), we can reach cell (7, 7) in exactly 6 seconds by going through the cells depicted in the picture above.
Example 2:
Input: sx = 3, sy = 1, fx = 7, fy = 3, t = 3 Output: false Explanation: Starting at cell (3, 1), it takes at least 4 seconds to reach cell (7, 3) by going through the cells depicted in the picture above. Hence, we cannot reach cell (7, 3) at the third second.
Constraints:
1 <= sx, sy, fx, fy <= 1090 <= t <= 109When 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 brute force approach explores every possible path to see if we can reach the destination within the given time. We systematically try moving in all directions at each step, checking if any of those paths lead us to the goal in the correct amount of time.
Here's how the algorithm would work step-by-step:
def is_reachable_at_time_brute_force(
start_row,
start_column,
finish_row,
finish_column,
allowed_time
):
# Special case: if start and finish are same
if start_row == finish_row and start_column == finish_column:
return allowed_time != 0
queue = [(start_row, start_column, 0)]
while queue:
current_row, current_column, current_time = queue.pop(0)
# Destination check: if destination and time align return True
if current_row == finish_row and current_column == finish_column:
if current_time == allowed_time:
return True
else:
continue
# Time check: Prune paths exceeding allowed_time
if current_time >= allowed_time:
continue
# Explore all 4 directions
possible_moves = [
(current_row + 1, current_column),
(current_row - 1, current_column),
(current_row, current_column + 1),
(current_row, current_column - 1),
]
for next_row, next_column in possible_moves:
queue.append((next_row, next_column, current_time + 1))
return FalseThe problem boils down to figuring out the shortest time needed to reach the destination and comparing it with the given time. We need to consider if a straight path or diagonal path is most efficient, and also handle edge cases where the starting point is the destination.
Here's how the algorithm would work step-by-step:
def is_reachable_at_time(start_row, start_column,
target_row, target_column, given_time):
row_difference = abs(target_row - start_row)
column_difference = abs(target_column - start_column)
#The minimum time required is the max of row and column difference.
minimum_time_required = max(row_difference, column_difference)
if start_row == target_row and start_column == target_column:
# Special case: starting and ending at the same point.
if given_time == 1:
return False
return True
if given_time < minimum_time_required:
return False
remaining_time = given_time - minimum_time_required
# If remaining time is even, we can always reach the destination.
if remaining_time % 2 == 0:
return True
else:
#When time is odd, only reachable if min_time > 1.
if minimum_time_required > 1:
return True
else:
return False| Case | How to Handle |
|---|---|
| Start and target cells are the same | If the time is greater than or equal to 1, it's reachable; otherwise, it's unreachable. |
| Time is insufficient to reach the target, even with the shortest path | Check if the time is less than the Manhattan distance between the start and target cells and return false. |
| Time is exactly equal to the Manhattan distance | Check if time is exactly equal to the Manhattan distance, meaning no extra moves allowed, and return true. |
| Time is sufficient to reach the target, but the shortest path requires passing through an obstacle preventing immediate arrival | Since we can move back and forth if time exceeds shortest distance we are always reachable |
| Integer overflow in calculating Manhattan distance with very large coordinates | Use long data types for calculations to prevent integer overflow. |
| Coordinates are extremely large, potentially causing performance issues | The constant time Manhattan distance calculation ensures efficient performance regardless of input size. |
| Either start or target coordinates are negative | The Manhattan distance calculation works correctly with negative coordinates. |
| Time is very large but the distance is relatively small | Check if the difference between the time and the Manhattan distance is non-negative and even, confirming reachability through repeated back-and-forth movements when time allows. |