1488. Avoid Flood in The City

Weekly Contest 194 - Q3, 其实都不算是很难的Q3, 但就是一直TLE. 对于很多时间复杂度比较大的操作不够谨慎。思路也不够开阔,自己算法工具箱里可以拿出来用的东西太少了。

比赛时候的思路是维护所有lake的状态,如果遇到雨下在已经 full 的 lake 上,就往回找最早可用的 work day,把它给dry了。但按照这个思路写出来的代码一直 TLE (也附在下面了),过不了。

其实这个思路是可以做的,时间复杂度大概在O(n*logn)级别,但我的问题出在「找最早可用的work day」这一部分,我的操作是:

  1. 先计算可用区间,

  2. 再看work里是否存在可用的

这样需要对 work 搜索很多次(更傻的是,用remove删元素时还要再多搜一次),导致运算成本一下子上去了。其实只要把这边改成:遍历work,看有没有元素在可用区间内,即可通过。有效代码如下:

Greedy Straight Forward 解法

class Solution:
    def avoidFlood(self, rains: List[int]) -> List[int]:
        ans = [-1 for _ in range(len(rains))]
        full = collections.defaultdict(lambda: -1)
        work = set()
        for day, lake in enumerate(rains):
            if lake == 0:
                work.add(day)
            if lake > 0:
                if full[lake] < 0:
                    full[lake] = day
                else:
                    prev = full[lake]
                    if day - prev <= 1:
                        return []
                    found = False
                    for i in range(prev, day):
                        if i in work:
                            work.remove(i)
                            ans[i] = lake
                            full[lake] = day
                            found = True
                            break
                    if not found:
                        return []
        
        for i in work:
            ans[i] = 1
        
        return ans

Discussion里另一个常见解法就是利用Heap 维护一个危机序列 toDry, 一直处理危机序列里面最紧迫的危机(最小的 day index),本质也是一种 greedy 搜索。

Heap 解法

class Solution:
    def avoidFlood(self, rains: List[int]) -> List[int]:
        dayRain = collections.defaultdict(list)
        ans = [-1] * len(rains)
        toDry = []
        
        # 遍历 rains, 记录各个湖下雨的 day index
        for day,lake in enumerate(rains):
            dayRain[lake].append(day)
        
        for i, lake in enumerate(rains):
            # 如果下雨
            if lake != 0:
                # 危机可以解决 -> 添加危机
                if dayRain[lake] and len(dayRain[lake])>1:
                    heapq.heappush(toDry, dayRain[lake][1])
                # 危机不可能解决 -> Game over
                if dayRain[lake] and dayRain[lake][0] < i: return []
            # 如果不下雨 -> 可以干活
            else:
                # 有活儿可干 -> 解决最紧迫的危机 (toDry 里面最小的 day index)
                if toDry:
                    ans[i] = rains[heapq.heappop(toDry)]
                    dayRain[ans[i]].pop(0) # 活儿干完,当前危机解除
                # 没活儿干 -> 随便 dry 一个
                else: ans[i] = 1
        return ans

Last updated

Was this helpful?