Tag
【贪心+二分】【数组】【2023-10-13】
题目来源
![](https://i-blog.csdnimg.cn/blog_migrate/41803a16eb3610aae2a1f4ce7f5a7b99.gif)
题目解读
现在有一些湖泊,在下雨的时候会向指定的湖泊中下雨,一旦下雨湖泊就会满。如果某个湖泊第二次下雨了,那么该湖泊就会发大水,我们需要在晴天的时候提前给一些湖泊排水,现在需要求的是在晴天的时候给哪些湖泊排水。
题目是有一点点不好理解的,只能多看看几遍,分析分析例子以便快速理解。
官方示例
![](https://i-blog.csdnimg.cn/blog_migrate/84eb53dcf2cf7200107a6e6e28d22c1c.gif)
解题思路
方法一:贪心+二分
使用一个哈希 lastIdx
表来记录湖泊上一次下雨的时间,现在遍历到的湖泊是 rains[i]
,如果之前已经遍历过了湖泊 rains[i]
,那么该湖泊这次就会发大水。为了避免发大水,需要在已经记录的晴天当中拿出一天的时间来给 rains[i]
湖泊排水,为了尽可能把排水机会留给其他的发大水的湖泊,我们选择给 rains[i]
排水的那一天为晴天中 >= i
的最小值。
实现代码
class Solution {
public:
vector<int> avoidFlood(vector<int>& rains) {
int n = rains.size();
vector<int> res(n, 1);
unordered_map<int, int> lastIdx;
set<int> zeros;
for (int i = 0; i < n; ++i) {
if (rains[i] == 0) {
zeros.insert(i);
}
else {
res[i] = -1;
if (lastIdx.count(rains[i])) { // 之前遍历过
auto it = zeros.lower_bound(lastIdx[rains[i]]);
if (it == zeros.end()) { // 两个湖泊下雨的时间之间没有晴天,没法排水
return {};
}
res[*it] = rains[i];
zeros.erase(it);
}
lastIdx[rains[i]] = i;
}
}
return res;
}
};
复杂度分析
时间复杂度:
n
l
o
g
n
nlogn
nlogn,
n
n
n 为数组 rains
的长度。有序集合中每次的插入和查询时间为
O
(
l
o
g
n
)
O(logn)
O(logn)。
空间复杂度: O ( n ) O(n) O(n),主要是有序集合和哈希表的时间开销。
其他语言
python3
from sortedcontainers import SortedList
class Solution:
def avoidFlood(self, rains: List[int]) -> List[int]:
res = [1] * len(rains)
zeros = SortedList()
lastIdx = {}
for i, rain in enumerate(rains):
if rain == 0:
zeros.add(i)
else:
res[i] = -1
if rain in lastIdx:
it = zeros.bisect(lastIdx[rain])
if it == len(zeros):
return []
res[zeros[it]] = rain
zeros.discard(zeros[it])
lastIdx[rain] = i
return res
写在最后
如果文章内容有任何错误或者您对文章有任何疑问,欢迎私信博主或者在评论区指出 💬💬💬。
如果大家有更优的时间、空间复杂度方法,欢迎评论区交流。
最后,感谢您的阅读,如果感到有所收获的话可以给博主点一个 👍 哦。