題目
原題鏈接
你的國家有無數個湖泊,所有湖泊一開始都是空的。當第 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 天選擇抽乾的湖泊。
如果有多種可行解,請返回它們中的 任意一個 。如果沒辦法阻止洪水,請返回一個 空的數組 。
思路
1.構造一個和數組rains
長度相同的結果數組 ans
;
2.使用HashMap
存儲當前時間已滿的湖泊,key
爲湖泊編號,value
爲下滿該湖泊的時間;
3.使用queue
存儲未下雨的天數;
4.循環遍歷rains數組:
5.如果當天不下雨,則記錄至queue
6.如果當天下雨,且該湖泊已滿,先將ans數組對應位置設爲-1,,然後從queue
中取出 該湖泊被下滿之後的第一個位置,
將ans數組的該天設置爲該湖泊的編號;map中的記錄修正爲當前時間;如果遍歷完了整
個隊列找不到符合條件的不下雨時間,則返回一個空數組,函數結束。
7.如果當天下雨,該湖泊未滿,先將ans數組對應位置設爲-1,然後將湖泊編號和時間存入map
。
8.循環結束。
9.如果queue中仍有剩餘元素,表示多餘的不下雨的日子,根據題意將對應ans對應位置都設爲1即可。
10.返回ans數組。
解析
主要比較複雜的部分在第六步。翻譯成白話就是:遇到一天(比如第N天)下雨的,且要下雨的那個湖泊當前是滿的。那麼就需要往前推,找到這個湖泊被下滿之後的不下雨的第一天,在那天把這個湖泊抽乾,以應對第N天的雨水。那麼到了第N天之後,這個湖泊其實還是滿的,下滿的時間也更新到了第N天。
代碼
public int[] avoidFlood(int[] rains) {
HashMap<Integer, Integer> map = new HashMap<>();
LinkedList<Integer> queue = new LinkedList<>();
int[] ans = new int[rains.length];
for (int i = 0; i< rains.length;i++) {
// 當天不下雨,在隊列中記錄時間
if (rains[i] == 0) {
queue.add(i);
} else {
// 當天下雨,且該池子已滿,需提前抽空
if (map.containsKey(rains[i])) {
boolean flag = false;
for(int j = 0;j < queue.size(); j++){
if (queue.get(j) > map.get(rains[i])) {
ans[i] = -1;
ans[queue.get(j)] = rains[i];
map.put(rains[i],i);
queue.remove(j);
flag = true;
break;
} else {
continue;
}
}
if(!flag) return new int[0];
} else {
// 當天下雨,且池子當前未滿
ans[i] = -1;
map.put(rains[i],i);
}
}
}
// 剩餘的不下雨的日子,都抽1號湖
if (!queue.isEmpty()) {
for (Iterator<Integer> iter=queue.iterator();iter.hasNext();) {
ans[iter.next()] = 1;
}
}
return ans;
}