• 2023-09-21 LeetCode每日一题(收集树中金币)


    2023-09-21每日一题

    一、题目编号

    2603. 收集树中金币
    
    • 1

    二、题目链接

    点击跳转到题目位置

    三、题目描述

    给你一个 n 个节点的无向无根树,节点编号从 0 到 n - 1 。给你整数 n 和一个长度为 n - 1 的二维整数数组 edges ,其中 edges[i] = [ai, bi] 表示树中节点 ai 和 bi 之间有一条边。再给你一个长度为 n 的数组 coins ,其中 coins[i] 可能为 0 也可能为 1 ,1 表示节点 i 处有一个金币

    一开始,你需要选择树中任意一个节点出发。你可以执行下述操作任意次:

    • 收集距离当前节点距离为 2 以内的所有金币,或者
    • 移动到树中一个相邻节点。
      你需要收集树中所有的金币,并且回到出发节点,请你返回最少经过的边数。

    如果你多次经过一条边,每一次经过都会给答案加一。

    示例 1
    在这里插入图片描述

    示例 2:
    在这里插入图片描述
    提示:

    • n == coins.length
    • 1 <= n <= 3 * 104
    • 0 <= coins[i] <= 1
    • edges.length == n - 1
    • edges[i].length == 2
    • 0 <= ai, bi < n
    • ai != bi
      edges 表示一棵合法的树。

    四、解题代码

    class Solution {
    public:
        int collectTheCoins(vector<int>& coins, vector<vector<int>>& edges) {
            int n = coins.size();
            vector<vector<int>> g(n);
            vector<int> degree(n);
            for (const auto& edge: edges) {
                int x = edge[0], y = edge[1];
                g[x].push_back(y);
                g[y].push_back(x);
                ++degree[x];
                ++degree[y];
            }
    
            int rest = n;
            {
                /* 删除树中所有无金币的叶子节点,直到树中所有的叶子节点都是含有金币的 */
                queue<int> q;
                for (int i = 0; i < n; ++i) {
                    if (degree[i] == 1 && !coins[i]) {
                        q.push(i);
                    }
                }
                while (!q.empty()) {
                    int u = q.front();
                    --degree[u];
                    q.pop();
                    --rest;
                    for (int v: g[u]) {
                        --degree[v];
                        if (degree[v] == 1 && !coins[v]) {
                            q.push(v);
                        }
                    }
                }
            }
            {
                /* 删除树中所有的叶子节点, 连续删除2次 */
                for (int _ = 0; _ < 2; ++_) {
                    queue<int> q;
                    for (int i = 0; i < n; ++i) {
                        if (degree[i] == 1) {
                            q.push(i);
                        }
                    }
                    while (!q.empty()) {
                        int u = q.front();
                        --degree[u];
                        q.pop();
                        --rest;
                        for (int v: g[u]) {
                            --degree[v];
                        }
                    }
                }
            }
    
            return rest == 0 ? 0 : (rest - 1) * 2;
        }
    };
    
    • 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
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60

    五、解题思路

    (1) 运用两次拓扑排序

  • 相关阅读:
    Redis 和 Memcache 的区别
    计算机网络相关知识点总结(二)
    k8s-pod管理 3
    数据中心通识
    0070__Postman如何导出接口的几种方法
    BIO、NIO、AIO三者的区别及其应用场景(结合生活例子,简单易懂)
    智能巡检系统有什么特点和功能?它是如何推动企业高效管理?
    GEO生信数据挖掘(六)实践案例——四分类结核病基因数据预处理分析
    uniapp实现表格冻结
    pdf怎么转图片,可得到高清图
  • 原文地址:https://blog.csdn.net/qq_56086076/article/details/133150799