1. 问题背景与题目理解
今天我们来拆解LeetCode第1488题"避免洪水泛滥"(Avoid Flood in The City)。这是一道来自第193场周赛的题目,难度标注为中等,但实际解决过程中有不少值得深入探讨的细节。题目描述的是在一个雨季连绵的国家,我们需要设计一套湖泊管理策略,防止洪水泛滥。
具体场景是:有一系列湖泊,第i天如果下雨就会填满某个特定湖泊(rains[i]表示该湖泊编号)。如果某湖泊已经装满水,再次下雨就会引发洪水。我们的目标是在不下雨的日子(rains[i]=0)选择抽干一个湖泊,避免后续发生洪水。
关键提示:抽干操作只能在下雨量为0的日子进行,且每次只能抽干一个湖泊
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 核心算法思路分析
2.1 问题转化与抽象
这道题本质上是一个调度问题,我们需要合理安排抽干操作的顺序。可以将问题分解为以下几个关键点:
- 记录每个湖泊最近一次被填满的时间
- 当某个湖泊即将被再次填满时,检查是否有可用的抽干机会
- 抽干操作必须在两次下雨之间完成
2.2 贪心算法的适用性
采用贪心算法是最直观的解决方案。具体思路是:
- 遍历每一天的降雨情况
- 维护一个哈希表记录已满的湖泊
- 当下雨填满已满湖泊时,从之前的晴天中找一个合适的日子抽干它
python复制def avoidFlood(rains):
from collections import defaultdict
import bisect
lake_days = defaultdict(list)
for day, lake in enumerate(rains):
if lake > 0:
lake_days[lake].append(day)
full = {}
dry_days = []
res = [1] * len(rains)
for day, lake in enumerate(rains):
if lake == 0:
dry_days.append(day)
continue
if lake in full:
prev_day = full[lake]
idx = bisect.bisect_right(dry_days, prev_day)
if idx == len(dry_days):
return []
dry_day = dry_days.pop(idx)
res[dry_day] = lake
res[day] = -1
full[lake] = day
return res
3. 实现细节与优化
3.1 数据结构的选择
为了实现高效查询,我们需要合理选择数据结构:
- 使用哈希表记录湖泊最近一次被填满的时间(O(1)查询)
- 使用有序数组存储可用的晴天(便于二分查找)
- 结果数组初始化为1(题目要求无操作时默认抽干1号湖)
3.2 边界条件处理
实际编码时需要特别注意以下边界情况:
- 连续多天下雨同一个湖泊
- 晴天出现在需要抽干操作之前
- 所有湖泊都未被填满的情况
- 没有足够晴天来处理所有潜在洪水
4. 复杂度分析与替代方案
4.1 时间复杂度
该算法的时间复杂度为O(nlogn),主要来自:
- 遍历降雨数组O(n)
- 二分查找操作O(logn)
- 数组插入/删除操作O(n)
4.2 空间复杂度
空间复杂度为O(n),用于存储:
- 湖泊到下雨日的映射
- 晴天日的列表
- 结果数组
4.3 替代方案对比
除了贪心算法,还可以考虑:
- 优先队列:将需要抽干的湖泊按紧急程度排序
- 双指针:在某些特定情况下可能更高效
- 动态规划:虽然可行但实现复杂度较高
5. 实战技巧与常见错误
5.1 调试技巧
在解决这类问题时,建议:
- 先手动模拟小规模测试用例
- 打印关键变量的中间状态
- 特别注意数组索引的边界
5.2 常见错误模式
根据社区提交记录,常见错误包括:
- 忘记处理连续的晴天
- 错误地假设抽干顺序
- 没有正确处理无解情况
- 默认返回值设置不当
5.3 测试用例设计
建议验证的测试用例:
python复制测试1: [1,2,3,4] → [-1,-1,-1,-1]
测试2: [1,2,0,0,2,1] → [-1,-1,2,1,-1,-1]
测试3: [1,2,0,1,2] → []
测试4: [1,0,2,0,2,1] → [-1,1,-1,2,-1,-1]
6. 扩展思考与实际应用
虽然这是一道算法题,但其核心思想可以应用于:
- 资源调度系统
- 缓存淘汰策略
- 任务优先级管理
- 实时系统的事件处理
在实际工程中,类似的场景可能还需要考虑:
- 操作的并行性
- 资源使用的优先级
- 操作的成本差异
- 系统的容错机制
这道题很好地展示了如何将现实问题抽象为算法问题,并通过合理的数据结构和算法设计找到高效解决方案。理解这类问题的模式,对提升解决复杂调度问题的能力大有裨益。
