首页 > 其他分享 >LC2603 收集树中金币

LC2603 收集树中金币

时间:2023-09-21 20:11:20浏览次数:40  
标签:结点 int coins 金币 push 树中 LC2603 deg

利用了拓扑排序思想的趣题。

答案要求统计“走过的边数”,这个不是很好统计,但是统计“哪些点不需要去”比较简单:

  1. 没有金币的子树不需要去;
  2. 删去 1 之后的叶子结点不需要去;
  3. 删去 1,2 之后的叶子结点不需要去。

可以证明,其他的点都需要去到。

删去上述结点的依据是度数(都是叶子结点)和金币,自然地想到使用拓扑排序处理。

细节上,因为答案要求的是边而不是点,故需要将“删除点”转化为“删除点到自己父节点的边”,用一个变量统计剩余边数即可;如果所有的点全部删完,变量的值变成 \(-1\),需要特判;因为要求回到出发点,答案为剩余边数乘以 \(2\)。

拓扑排序应当注意逐层删除,实现时切勿跨层删点,否则会导致点的度数出错。

下面是 AC 代码:

int collectTheCoins(vector<int>& coins, vector<vector<int>>& edges) {
        int n = coins.size();
        int m = n - 1;
        vector<vector<int>> g(n);
        vector<int> deg(n);
        for(auto& e : edges) {
            g[e[0]].push_back(e[1]);
            g[e[1]].push_back(e[0]);
            ++deg[e[0]], ++deg[e[1]];
        }
        queue<int> q;
        for(int i = 0; i < n; i++) {
            if(deg[i] == 1 && !coins[i]){ //没有金币的叶子结点
                q.push(i);
            }
        }
        while(!q.empty()) { //第一次拓扑排序,把没有金币的子树全部消灭
            --m;
            int u = q.front();
            q.pop();
            for(int v : g[u]){
                if(--deg[v] == 1 && !coins[v]){
                    q.push(v);
                }
            }
        }
        for(int u = 0; u < n; u++) {
            if(deg[u] == 1 && coins[u]) { // 有金币的叶子结点
                q.push(u);
            }
        }
        m -= q.size();
        while(!q.empty()) {
            int u = q.front();
            q.pop();
            for(int v : g[u]) {
                if(--deg[v] == 1) { // 仅删除两层,不再入队
                    m--;
                }
            }
        }
        return max(m * 2, 0); // 避免边数出现 -1
    }

标签:结点,int,coins,金币,push,树中,LC2603,deg
From: https://www.cnblogs.com/th19/p/17720839.html

相关文章

  • 124. 二叉树中的最大路径和
    二叉树中的路径被定义为一条节点序列,序列中每对相邻节点之间都存在一条边。同一个节点在一条路径序列中至多出现一次。该路径至少包含一个节点,且不一定经过根节点。路径和是路径中各节点值的总和。给你一个二叉树的根节点root,返回其最大路径和。示例1:输入:root=......
  • 《剑指Offer》-34-二叉树中和为某一值的路径
    思路要求是从根节点开始的路径,这会比从任意节点开始的路径简单很多思路是从根节点开始遍历每一条路径,如果和没有达到目标值就继续向下遍历大于就回退,等于就返回到结果集中,可以看到这是一个回溯动作实际过程中,首先不管是等于还是大于,回退pop()操作都要执行,这样才不会影响到后......
  • 230. 二叉搜索树中第K小的元素
    给定一个二叉搜索树的根节点root,和一个整数k,请你设计一个算法查找其中第k个最小元素(从1开始计数)。示例1:输入:root=[3,1,4,null,2],k=1输出:1>代码classSolution{public:vector<int>res;intaaa;voidtraversal(TreeNode*root,intk){......
  • P2669 [NOIP2015 普及组] 金币
    题目背景NOIP2015普及组T1题目描述国王将金币作为工资,发放给忠诚的骑士。第一天,骑士收到一枚金币;之后两天(第二天和第三天),每天收到两枚金币;之后三天(第四、五、六天),每天收到三枚金币;之后四天(第七、八、九、十天),每天收到四枚金币……;这种工资发放模式会一直这样延续下去:当连......
  • #yyds干货盘点# LeetCode程序员面试金典:二叉搜索树中第K小的元素
    题目:给定一个二叉搜索树的根节点 root ,和一个整数 k ,请你设计一个算法查找其中第 k 个最小元素(从1开始计数)。 示例1:输入:root=[3,1,4,null,2],k=1输出:1示例2:输入:root=[5,3,6,2,4,null,null,1],k=3输出:3代码实现:classSolution{publicintkthSmallest(......
  • canvas+js接金币小游戏
    忙里偷闲,让UI小伙伴帮忙搞了几个图片元素,利用飞机大战代码进行修改,做个接金币小游戏~varcanvas=document.getElementById("canvas");varcontext=canvas.getContext("2d");varimgWidth=window.innerWidth;varimgHeight=window.innerHeigh......
  • 代码随想录:● 654.最大二叉树 ● 617.合并二叉树 ● 700.二叉搜索树中的搜索 ● 98
     654.最大二叉树 给定一个不含重复元素的整数数组。一个以此数组构建的最大二叉树定义如下:二叉树的根是数组中的最大元素。左子树是通过数组中最大值左边部分构造出的最大二叉树。右子树是通过数组中最大值右边部分构造出的最大二叉树。通过给定的数组构建最大二叉树,并且输出这个......
  • java版本剑指offer:在二叉树中找到两个节点的最近公共祖先
    java版本剑指offer:在二叉树中找到两个节点的最近公共祖先描述给定一棵二叉树(保证非空)以及这棵树上的两个节点对应的val值o1和o2,请找到o1和o2的最近公共祖先节点。注:本题保证二叉树中每个节点的val值均不相同。示例1输入:[3,5,1,6,2,0,8,#,#,7,4],5,1返回值:3方法一:递......
  • 【Leetcode刷题记录】1、统计参与通信的服务器;2、统计二叉树中好节点的数目;3、从两个
    1、统计参与通信的服务器题目:这里有一幅服务器分布图,服务器的位置标识在 m*n 的整数矩阵网格 grid 中,1表示单元格上有服务器,0表示没有。如果两台服务器位于同一行或者同一列,我们就认为它们之间可以进行通信。请你统计并返回能够与至少一台其他服务器进行通信的服务器的......
  • 20.2 设备树中的 platform 驱动编写
    一、设备树下的platform驱动  platform驱动框架分为总线、设备和驱动,总线不需要我们去管理,这个是Linux内核提供。在有了设备树的前提下,我们只需要实现platform_driver即可。 1. 修改pinctrl-stm32.c文件   先复习一下pinctrl子系统和gpio子系统,pinctrl子......