三、 避免洪水氾濫(Weekly Contest 194)

題目描述:
你的國家有無數個湖泊,所有湖泊一開始都是空的。當第 n 個湖泊下雨的時候,如果第 n 個湖泊是空的,那麼它就會裝滿水,否則這個湖泊會發生洪水。你的目標是避免任意一個湖泊發生洪水。

給你一個整數數組 rains ,其中:

rains[i] > 0 表示第 i 天時,第 rains[i] 個湖泊會下雨。
rains[i] == 0 表示第 i 天沒有湖泊會下雨,你可以選擇 一個 湖泊並 抽乾 這個湖泊的水。
請返回一個數組 ans ,滿足:

ans.length == rains.length
如果 rains[i] > 0 ,那麼ans[i] == -1 。
如果 rains[i] == 0 ,ans[i] 是你第 i 天選擇抽乾的湖泊。
如果有多種可行解,請返回它們中的 任意一個 。如果沒辦法阻止洪水,請返回一個 空的數組 。

請注意,如果你選擇抽乾一個裝滿水的湖泊,它會變成一個空的湖泊。但如果你選擇抽乾一個空的湖泊,那麼將無事發生(詳情請看示例 4)。

示例 1:

輸入:rains = [1,2,3,4]
輸出:[-1,-1,-1,-1]
解釋:第一天後,裝滿水的湖泊包括 [1]
第二天後,裝滿水的湖泊包括 [1,2]
第三天後,裝滿水的湖泊包括 [1,2,3]
第四天後,裝滿水的湖泊包括 [1,2,3,4]
沒有哪一天你可以抽乾任何湖泊的水,也沒有湖泊會發生洪水。
示例 2:

輸入:rains = [1,2,0,0,2,1]
輸出:[-1,-1,2,1,-1,-1]
解釋:第一天後,裝滿水的湖泊包括 [1]
第二天後,裝滿水的湖泊包括 [1,2]
第三天後,我們抽乾湖泊 2 。所以剩下裝滿水的湖泊包括 [1]
第四天後,我們抽乾湖泊 1 。所以暫時沒有裝滿水的湖泊了。
第五天後,裝滿水的湖泊包括 [2]。
第六天後,裝滿水的湖泊包括 [1,2]。
可以看出,這個方案下不會有洪水發生。同時, [-1,-1,1,2,-1,-1] 也是另一個可行的沒有洪水的方案。
示例 3:

輸入:rains = [1,2,0,1,2]
輸出:[]
解釋:第二天後,裝滿水的湖泊包括 [1,2]。我們可以在第三天抽乾一個湖泊的水。
但第三天後,湖泊 1 和 2 都會再次下雨,所以不管我們第三天抽乾哪個湖泊的水,另一個湖泊都會發生洪水。
示例 4:

輸入:rains = [69,0,0,0,69]
輸出:[-1,69,1,1,-1]
解釋:任何形如 [-1,69,x,y,-1], [-1,x,69,y,-1] 或者 [-1,x,y,69,-1] 都是可行的解,其中 1 <= x,y <= 10^9
示例 5:

輸入:rains = [10,20,20]
輸出:[]
解釋:由於湖泊 20 會連續下 2 天的雨,所以沒有沒有辦法阻止洪水。

提示:

1 <= rains.length <= 10^5
0 <= rains[i] <= 10^9

來源:力扣(LeetCode)
鏈接:https://leetcode-cn.com/problems/avoid-flood-in-the-city
著作權歸領釦網絡所有。商業轉載請聯繫官方授權,非商業轉載請註明出處。

這道題目有點難度,就是說:你得保證兩個相鄰的湖泊儘可能乾涸
看看別人的思路:

import java.util.*;

class Solution {
    public int[] avoidFlood(int[] rains) {
        int n = rains.length;
        int[] ans = new int[n];
        //存儲可以進行排水工作的日子
        TreeSet<Integer> work = new TreeSet<>();
        //存儲"湖->該湖最後一次下雨的日子"的映射
        Map<Integer, Integer> water = new HashMap<>();
        for (int i = 0; i < n; i++) {
            if (rains[i] == 0) {
                //當天不下雨,可以進行排水工作,但具體要進行哪一個湖的排水只能等後面需要的時候才知道,所以先存起來
                work.add(i);
            } else {
                Integer last = water.get(rains[i]);
                if (last != null) { //這個湖之前下過雨
                    //用TreeSet的higher方法找到該湖最後一次下雨後最早可以進行排水工作的日子
                    //之所以要最早的,是因爲越靠後的可用工作日越能進行潛在的別的湖的排水
                    Integer toWork = work.higher(last);
                    //如果這樣的日子不存在,說明無法避免洪水
                    if (toWork == null) return new int[0];
                    //確定toWork那天進行rains[i]這個湖的排水工作,並將其移出可用工作日的集合
                    ans[toWork] = rains[i];
                    work.remove(toWork);
                }
                //將rains[i]這個湖最後一次下雨的日期更新爲i
                water.put(rains[i], i);
                // i這天下了雨不能進行排水
                ans[i] = -1;
            }
        }
        // 某些工作日可能不需要進行排水(對應的ans[i]保留爲初始的0),但按照題意還是要填上某個正數
        for (int i = 0; i < n; i++) {
            if (ans[i] == 0) ans[i] = 1;
        }
        return ans;
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章