問題描述:
你的國家有無數個湖泊,所有湖泊一開始都是空的。當第 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 天的雨,所以沒有沒有辦法阻止洪水。
大體思路:
乙個貪心思路,遇到晴天時,應該優先選擇裡當天之後最近一次再次裝滿水的湖泊抽乾,以示例2為例,
rains = [1,2,0,0,2,1]
第三天是個晴天,發現裡它最近再次裝滿水的湖泊是2號湖泊,所以應該優先抽乾二號湖泊的水。
解法一:直接貪心
使用一set儲存已經裝滿水的湖泊號,遍歷過程中若當天下雨,就判斷set中是否存在該湖泊,若存在則說明該湖泊沒能抽乾,引發渾水;否則將下雨的湖泊號存入set。若當前晴天,就在從當天的下一天開始遍歷,找到第乙個再次下雨的湖泊,並將其從set中刪除。該方法o(n^2),直接超時了...**如下:
class solution解法二:貪心 + 二分result[i] = -1;
set.add(rains[i]);
continue;
}result[i] = 1;//隨便抽乙個
for(int j = i + 1; j < rains.length; j++)}}
return result;
}}
首先使用乙個list儲存所有晴天的日期(從前至後)。使用一map儲存下雨的湖泊號和日期(key = 下雨湖泊號 value = 日期)。
遍歷過程中,若當天下雨,判斷該湖泊之前是否下雨,若下之前亦下過雨,則此時在晴天list中二分查詢乙個距上次下雨之後最近的晴天(大於target值中最小的元素),並在該天對該湖泊放水,若找不到則證明發洪水了,最後更新map;若當天不下雨則將當天日期存入list。時間複雜度o(nlog(n)),實現**如下:
class solution
result[i] = -1;
if(map.containskey(rains[i]))
int index = find(sunday, pre);
result[sunday.remove(index)] = rains[i];
}map.put(rains[i], i);
}return result;
}public int find(listlist, int target)else
}if(list.get(left) > target)
return right;
}}
解法三:貪心 + 最小堆
解法一中我們知道,遇到晴天時我們應該找到其之後的再次滿水的湖泊,對其放水。因此使用一名為nextrain的陣列儲存下次下雨的時間,nextrain[i] 為rain[i]湖泊下次下雨的日期;使用一map儲存湖泊狀態(是否有水);使用一最小堆儲存下一次下雨時間。
遍歷過程中若當天有雨,則判斷當天下雨的湖泊之前是否有水,有水則說明已經發洪水了,否則將當天nextrain[i]存入最小堆,;遇到晴天時,從最小堆中彈出乙個元素,該元素時裡當天最近的再次下雨的日期,因此對該日期對應的湖泊放水即可。
實現**如下:(時間複雜度:o(nlog(n)))
class solution
}maphaswater = new hashmap<>();
queueminheap = new priorityqueue<>();
int result = new int[rains.length];
for(int i = 0; i < rains.length; i++)
haswater.put(rains[i], true);
minheap.add(nextrain[i]);
}elseelse}}
return result;
}}
Leetcode1陣列練習
31.next permutation class solution def plusone self,digits list int list int l 1 c 0if len digits 0 return digits cur len digits 1 while cur 1 if digi...
LeetCode 1 兩數之和
給定乙個整數數列,找出其中和為特定值的那兩個數。你可以假設每個輸入都只會有一種答案,同樣的元素不能被重用。示例 給定 nums 2,7,11,15 target 9 因為 nums 0 nums 1 2 7 9 所以返回 0,1 step 1 class solution object def tw...
leetcode 1 兩數之和
1.兩數之和 這道題和程式設計之法上面的題目有以下幾個不同 1 題目所給定的陣列是無序的,程式設計之法裡面是預設有序的 2 要求輸出原陣列的序號,如果用乙個結構體維護陣列下標,那麼需要o n 的空間,顯然不是最好的方法 3 題目中包含負數,之前想用數值直接表示陣列下標,陣列值為原來的真正陣列下標,但...