Your country has an infinite number of lakes. Initially, all the lakes are empty, but when it rains over the nth
lake, the nth
lake becomes full of water. If it rains over a lake that is full of water, there will be a flood. Your goal is to avoid floods in any lake.
Given an integer array rains
where:
rains[i] > 0
means there will be rains over the rains[i]
lake.rains[i] == 0
means there are no rains this day and you can choose one lake this day and dry it.Return an array ans
where:
ans.length == rains.length
ans[i] == -1
if rains[i] > 0
.ans[i]
is the lake you choose to dry in the ith
day if rains[i] == 0
.If there are multiple valid answers return any of them. If it is impossible to avoid flood return an empty array.
Notice that if you chose to dry a full lake, it becomes empty, but if you chose to dry an empty lake, nothing changes.
Example 1:
Input: rains = [1,2,3,4]
Output: [-1,-1,-1,-1]
Example 2:
Input: rains = [1,2,0,0,2,1]
Output: [-1,-1,2,1,-1,-1]
Example 3:
Input: rains = [1,2,0,1,2]
Output: []
Explain how to approach this problem, including the complexity analysis. Show code.
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 brute force approach to avoiding floods is like trying every possible watering schedule to see if any works. We'll look at each day and, for rainy days, just move on. For non-rainy days, we’ll simulate watering each lake one at a time to see if doing so causes a flood in the future.
Here's how the algorithm would work step-by-step:
def avoid_flood_brute_force(rains):
number_of_lakes = max(rains) if rains else 0
full_lakes = [False] * (number_of_lakes + 1)
result = [-1] * len(rains)
def can_avoid_flood(day_index):
if day_index == len(rains):
return True
rain = rains[day_index]
if rain > 0:
if full_lakes[rain]:
return False
full_lakes[rain] = True
result[day_index] = -1
return can_avoid_flood(day_index + 1)
else:
# Try watering each lake one by one
for lake_to_water in range(1, number_of_lakes + 1):
original_full_lakes = full_lakes[:]
full_lakes[lake_to_water] = False
result[day_index] = lake_to_water
if can_avoid_flood(day_index + 1):
return True
# Backtrack: Restore the original state
full_lakes = original_full_lakes
# No solution found for this day
result[day_index] = 0
return False
if can_avoid_flood(0):
return result
else:
return []
The core idea is to track future rain events and proactively use dry days to prevent floods. We will prioritize using dry days for cities that will flood soonest, rather than simply processing events in order. This avoids brute-force checking of all possibilities.
Here's how the algorithm would work step-by-step:
def avoid_flood(rains): last_rain = {}
future_rain = []
answer = []
for day, city in enumerate(rains):
if city > 0:
# If raining, check for flood
if city in last_rain:
return []
last_rain[city] = day
answer.append(-1)
else:
# Find which city to dry out first.
dry_city = 0
closest_rain = float('inf')
city_to_dry = -1
for rained_city in list(last_rain.keys()):
next_rain_day = float('inf')
for future_day in range(day + 1, len(rains)):
if rains[future_day] == rained_city:
next_rain_day = future_day
break
if next_rain_day < closest_rain:
closest_rain = next_rain_day
city_to_dry = rained_city
# Prioritize the city that rains soonest
if city_to_dry != -1:
answer.append(city_to_dry)
del last_rain[city_to_dry]
else:
answer.append(1)
return answer
Case | How to Handle |
---|---|
Null or empty input array | Return an empty array or an error message indicating invalid input, depending on problem specifications. |
Input array with all elements equal to zero. | The algorithm should handle rain correctly and avoid floods, as long as the zeros correspond to non-rainy days. |
Large input array leading to potential memory issues with data structures. | Optimize data structure choices (e.g., using generators if possible) or algorithms to minimize memory footprint. |
A rain event occurs on a day for which there's already a filled lake, with no intermediate dry days to resolve it. | Return an empty array, indicating that no valid solution (flood avoidance) is possible. |
Consecutive rain events for the same lake without any drying days in between. | Return an empty array, as a flood is unavoidable with current drying capabilities. |
No rain events at all - only drying days provided. | Return an array of -1 for each day, because it wasn't raining. |
Drying days appear before any lake has been filled. | Choose any arbitrary lake to dry (if there are filled lakes), or return -1 if no lakes are filled yet. |
Maximum integer value used for the lake identifiers, potentially causing overflow issues if used for arithmetic operations. | Handle potentially large numbers gracefully by either using appropriate data types (e.g., long) or alternative data representation. |