• 【每日一题】避免洪水泛滥


    Tag

    【贪心+二分】【数组】【2023-10-13】


    题目来源

    1488. 避免洪水泛滥


    题目解读

    现在有一些湖泊,在下雨的时候会向指定的湖泊中下雨,一旦下雨湖泊就会满。如果某个湖泊第二次下雨了,那么该湖泊就会发大水,我们需要在晴天的时候提前给一些湖泊排水,现在需要求的是在晴天的时候给哪些湖泊排水。

    题目是有一点点不好理解的,只能多看看几遍,分析分析例子以便快速理解。

    官方示例


    解题思路

    方法一:贪心+二分

    使用一个哈希 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;
        }
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    复杂度分析

    时间复杂度: 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
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    写在最后

    如果文章内容有任何错误或者您对文章有任何疑问,欢迎私信博主或者在评论区指出 💬💬💬。

    如果大家有更优的时间、空间复杂度方法,欢迎评论区交流。

    最后,感谢您的阅读,如果感到有所收获的话可以给博主点一个 👍 哦。

  • 相关阅读:
    LeetCode Algorithm 1472. 设计浏览器历史记录
    背完这套 Java 面试八股文,自动解锁面试牛逼症被动技能
    [晕事]今天做了件晕事31, gre 抓到半边
    Android Studio 导入工程&Gradle和JDK配置&修改工程名称&修改包名
    python数据分析与可视化
    使用Plotly可视化
    糟糕,CPU100%了!!!
    vmware: 磁盘加载问题导致,emergency mode: login incorrect 滚动打印
    openGauss学习笔记-103 openGauss 数据库管理-管理数据库安全-客户端接入之SSL证书管理-证书生成
    MybatisPlus学习笔记
  • 原文地址:https://blog.csdn.net/weixin_54383080/article/details/133812145