【数据结构和算法】到达首都的最少油耗

其他系列文章导航

Java基础合集
数据结构与算法合集

设计模式合集

多线程合集

分布式合集

ES合集


文章目录

其他系列文章导航

文章目录

前言

一、题目描述

二、题解

三、代码

四、复杂度分析


前言

这是力扣的2477题,难度为中等,解题方案有很多种,本文讲解我认为最奇妙的一种。


一、题目描述

给你一棵 n 个节点的树(一个无向、连通、无环图),每个节点表示一个城市,编号从 0 到 n - 1 ,且恰好有 n - 1 条路。0 是首都。给你一个二维整数数组 roads ,其中 roads[i] = [ai, bi] ,表示城市 ai 和 bi 之间有一条 双向路 。

每个城市里有一个代表,他们都要去首都参加一个会议。

每座城市里有一辆车。给你一个整数 seats 表示每辆车里面座位的数目。

城市里的代表可以选择乘坐所在城市的车,或者乘坐其他城市的车。相邻城市之间一辆车的油耗是一升汽油。

请你返回到达首都最少需要多少升汽油。

示例 1:

输入:roads = [[0,1],[0,2],[0,3]], seats = 5
输出:3
解释:
- 代表 1 直接到达首都,消耗 1 升汽油。
- 代表 2 直接到达首都,消耗 1 升汽油。
- 代表 3 直接到达首都,消耗 1 升汽油。
最少消耗 3 升汽油。

示例 2:

输入:roads = [[3,1],[3,2],[1,0],[0,4],[0,5],[4,6]], seats = 2
输出:7
解释:
- 代表 2 到达城市 3 ,消耗 1 升汽油。
- 代表 2 和代表 3 一起到达城市 1 ,消耗 1 升汽油。
- 代表 2 和代表 3 一起到达首都,消耗 1 升汽油。
- 代表 1 直接到达首都,消耗 1 升汽油。
- 代表 5 直接到达首都,消耗 1 升汽油。
- 代表 6 到达城市 4 ,消耗 1 升汽油。
- 代表 4 和代表 6 一起到达首都,消耗 1 升汽油。
最少消耗 7 升汽油。

示例 3:

输入:roads = [], seats = 1
输出:0
解释:没有代表需要从别的城市到达首都。

提示:

  • 1 <= n <= 105
  • roads.length == n - 1
  • roads[i].length == 2
  • 0 <= ai, bi < n
  • ai != bi
  • roads 表示一棵合法的树。
  • 1 <= seats <= 105

二、题解

本题用的贪心 + DFS解题。

这道题其实是要找到 树结构中所有节点到根节点的最小开销和 。

题目中的每个城市其实就是树结构中的一个节点,除了根节点外,每个节点都要从自身出发到达根节点,这其实就是根节点到每个节点的路径。【深度优先搜索先准备着】

每个节点之间一辆车的转移的开销为 1,我们要让开销和最小,那么就要使每个节点之间的转移车尽量的少。

那么怎么安排每个节点之间转移的车辆数呢,我们可以统计途径每个节点的代表人数有多少个,这些代表从当前节点往根节点方向转移到下一个节点【树结构,只有一种转移方式】需要车辆数,一定是 代表人数除以车的容量然后向上取整。

经过每个节点的代表人数就 是以这个节点为根的子树的节点数 , 我们可以通过深度优先搜索递归处理时, 返回当前节点为根的子树的节点数。

注意:

通过向下取整得到向上取整的策略:

本文用的是Math.ceil()方法,或者你也可以使用 (m + n - 1) / n,原理就不推导了。

根节点不转移:

深度优先搜索的递归中, 对城市 0, 其没有要转移的下一个节点, 因此不能计算转移消耗的汽油数。


三、代码

Java版本:

class Solution {
    //测试代码
    public static void main(String[] args) {
        int[][] roads = {{0, 1}, {0, 2}, {0, 3}};
        int seats = 5;
        long fuel = minimumFuelCost(roads, seats);
        System.out.println(fuel);
    }

    private static long fuel = 0;//耗油量

    public static long minimumFuelCost(int[][] roads, int seats) {
        int n = roads.length + 1;
        List<List<Integer>> tree = new ArrayList<>();//生成树结构
        for (int i = 0; i < n; i++) {
            tree.add(new ArrayList<>());
        }
        for (int[] r : roads) {//把每个国家的邻居存入小list,本国是大list,例如{{123}},代表0国,邻国123
            tree.get(r[0]).add(r[1]);
            tree.get(r[1]).add(r[0]);
        }
        boolean[] visited = new boolean[n];//标记城市是否遍历
        visited[0] = true;//初始标记首都已遍历
        dfs(0, tree, visited, seats);//从0节点开始深度优先搜索寻找每一条路径
        return fuel;
    }

    private static int dfs(int city, List<List<Integer>> tree, boolean[] visited, int seats) {
        int people = 1;//每座城市初始一个代表
        for (int neighbor : tree.get(city)) {//遍历邻国
            if (!visited[neighbor]) {
                visited[neighbor] = true;//标记遍历成功
                people += dfs(neighbor, tree, visited, seats);// 累加到达当前城市的代表人数
            }
        }
        if (city != 0) {// city 不为 0 ,就需要在移动到下一个节点,people 个代表需要的车辆数等于 people ÷ seats 向上取整
            fuel += Math.ceil((double) people / seats);//每辆车消耗1汽油
        }
        return people;
    }
}

C++版本:

class Solution {
public:
    long long minimumFuelCost(vector<vector<int>>& roads, int seats) {
        int n = roads.size() + 1;
        vector<int> g[n];
        for (auto& e : roads) {
            int a = e[0], b = e[1];
            g[a].emplace_back(b);
            g[b].emplace_back(a);
        }
        long long ans = 0;
        function<int(int, int)> dfs = [&](int a, int fa) {
            int sz = 1;
            for (int b : g[a]) {
                if (b != fa) {
                    int t = dfs(b, a);
                    ans += (t + seats - 1) / seats;
                    sz += t;
                }
            }
            return sz;
        };
        dfs(0, -1);
        return ans;
    }
};

 Python3版本:

class Solution:
    def minimumFuelCost(self, roads: List[List[int]], seats: int) -> int:
        def dfs(a: int, fa: int) -> int:
            nonlocal ans
            sz = 1
            for b in g[a]:
                if b != fa:
                    t = dfs(b, a)
                    ans += ceil(t / seats)
                    sz += t
            return sz

        g = defaultdict(list)
        for a, b in roads:
            g[a].append(b)
            g[b].append(a)
        ans = 0
        dfs(0, -1)
        return ans


四、复杂度分析

时间复杂度 O(n),空间复杂度 O(n)。其中 n 为节点数。


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/221157.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

用友NC Cloud FileParserServlet反序列化RCE漏洞复现

0x01 产品简介 用友 NC Cloud 是一种商业级的企业资源规划云平台,为企业提供全面的管理解决方案,包括财务管理、采购管理、销售管理、人力资源管理等功能,实现企业的数字化转型和业务流程优化。 0x02 漏洞概述 用友 NC Cloud FileParserServlet接口存在反序列化代码执行漏…

Amazon CodeWhisperer 正式可用, 并面向个人开发者免费开放

文章作者&#xff1a;深度-围观 北京——2023年4月18日&#xff0c;亚马逊云科技宣布&#xff0c;实时 AI 编程助手 Amazon CodeWhisperer 正式可用&#xff0c;同时推出的还有供所有开发人员免费使用的个人版&#xff08;CodeWhisperer Individual&#xff09;。CodeWhisperer…

微服务1 springcloud学习笔记P1-P40

b微服务技术栈_哔哩哔哩_bilibili 文档资料: 链接&#xff1a;https://pan.baidu.com/s/1P_Ag1BYiPaF52EI19A0YRw?pwdd03r 提取码&#xff1a;d03r 一 了解微服务技术 二 Eureka (1) Eureka配置 (2) 注册user-service (3) 总结 Ribbon 负载均衡 (1) 流程 三 nacos配置管理…

在AWS EC2中部署和使用Apache Superset的方案

大纲 1 Superset部署1.1 启动AWS EC21.2 下载Superset Docker文件1.3 修改Dockerfile1.4 配置管理员1.5 结果展示1.6 检查数据库驱动1.7 常见错误处理 2 Glue&#xff08;可选参考&#xff09;3 IAM与安全组3.1 使用AWS Athena3.2 使用AWS RedShift或AWS RDS3.2.1 查看AWS Reds…

JavaScript <md5加密的两种不同输出结果分析>--案例(二点一)

前言: 问题是这样的,在浏览器中看到这段代码 然后在控制台进行输出.得到: 紧接着,就在,js文件里面进行转译: 可是,得到的结果是: 这是问题!!! 正题: 为什么相同的js代码,在 .js 文件中的输出与 Chrome 控制台中的输出不一样? 环境差异&#xff1a;不同的JavaScript环境&…

dante(centos)安装

下载安装包 https://www.inet.no/dante/doc/latest/config/index.html 下载软件 解压 tar -zxvf dante-1.4.3.tar.gz 或者 wget http://www.inet.no/dante/files/dante-1.4.3.tar.gz tar -xvzf dante-1.4.3.tar.gz 编译 cd dante-1.4.3 yum install gcc make -y ##编译必备 …

活动目录是什么?

企业在进行数字化转型时&#xff0c;也会面临日益增长的网络用户和复杂的身份管理需求。为了高效地管理用户身份、控制访问权限以及保护企业的数据安全&#xff0c;许多企业选择使用微软的Active Directory&#xff0c;即微软活动目录&#xff0c;来作为网络身份管理系统。 1、…

DS图应用--最短路径

Description 给出一个图的邻接矩阵&#xff0c;再给出指定顶点v0&#xff0c;求顶点v0到其他顶点的最短路径 Input 第一行输入t&#xff0c;表示有t个测试实例 第二行输入n&#xff0c;表示第1个图有n个结点 第三行起&#xff0c;每行输入邻接矩阵的一行&#xff0c;以此类…

关于先更新再缓存这种缓存方案设计的思考

这两天正在做公司缓存方面的设计&#xff0c;然后就把自己的思考过程整理一下。 网上对于这块的内容讲解也非常的多&#xff0c;有些说的也都非常的在理&#xff0c;关于缓存一致性的方案也就那么几种&#xff0c;如&#xff1a;先更新、再删&#xff0c;先删、在更新&#xff…

【Polar靶场WEB签到】

题目&#xff1a; <?phperror_reporting(0);$file $_GET[file];if(!isset($file))$file 1;$file str_replace(../, , $file);include_once($file.".php");highlight_file(__FILE__); ?>解答&#xff1a;1、进入index页面&#xff0c;说让你加弟弟&#x…

WordPiece词表的创建

文章目录 一、简单介绍二、步骤流程2.1 预处理2.2 计数2.3 分割2.4 添加subword 三、代码实现 本篇内容主要介绍如何根据提供的文本内容创建 WordPiece vocabulary&#xff0c;代码来自谷歌&#xff1b; 一、简单介绍 wordpiece的目的是&#xff1a;通过考虑单词内部构造&…

算法通关村第十七关-青铜挑战贪心算法思想

大家好我是苏麟 , 今天说说贪心算法 . 贪心思想很难用理论解释&#xff0c;本文我们先通过案例来感受一下贪心是如何解决问题的 大纲 难以理解的贪心算法贪心问题举例分发饼干柠檬水找零分发糖果 难以理解的贪心算法 贪心的思想非常不好解释&#xff0c;而且越使用权威的语言解…

【隐私计算】安全三方计算(3PC)的加法和乘法计算协议

ABY3中采用replicated secret sharing&#xff08;复制秘密分享&#xff09;机制&#xff0c;即2-out-of-3秘密分享&#xff0c;三个参与方的每一方都拥有share中的两份。下面来看一下这样做有什么好处。 2-out-of-3秘密分享 有 x , y x, y x,y两个操作数&#xff0c;先进行秘…

ttkefu在线客服软件新版即将上线——引领客服行业迈向新篇章

在线客服软件已经成为企业与用户之间沟通的重要桥梁。作为领先的客服解决方案提供商&#xff0c;ttkefu即将推出全新版本的在线客服软件&#xff0c;为客服行业注入新的活力。 一、ttkefu新版在线客服软件的主要特点 智能化客户管理&#xff1a;新版软件将采用先进的自然语言…

sd_webui的实用插件,prompt/lama/human matting/...,持续开源更新!!

热烈欢迎大家在git上star&#xff01;&#xff01;&#xff01;冲鸭&#xff01;&#xff01;&#xff01; 1.prompt优化插件 GitHub - leeguandong/sd_webui_beautifulprompt: beautifulprompt extension performs stable diffusion automatic prompt engineering on a bro…

抖音本地生活服务商申请入口在哪里?具体流程是怎样的?

不论是抖音的本地生活业务&#xff0c;还是后来的支付宝、视频号的本地生活业务&#xff0c;因为市场体量足够庞大&#xff0c;市场前景广阔&#xff0c;一直很受各大创业者的追捧。那么&#xff0c;如此火热的本地生活项目&#xff0c;想要申请成为服务商&#xff0c;具体的申…

某60区块链安全之JOP实战二学习记录

区块链安全 文章目录 区块链安全Jump Oriented Programming实战二实验目的掌握对EVM逆向能力实验环境实验工具实验原理实验内容Jump Oriented Programming实战二 实验步骤Jump Oriented Programming实战二 实验目的 学会使用python3的web3模块 学会分析以太坊智能合约中中Jum…

26、卷积 - 实际上是一个特征提取器

矩阵乘法的本质是特征的融合&#xff0c;卷积算法的本质是特征的提取。 回想一下之前所有介绍卷积的时候&#xff0c;描述了一种卷积运算的场景&#xff0c;那就是一个窗口在图片上滑动&#xff0c;窗口中的数值是卷积核的参数&#xff0c;也就是权值。 卷积的计算本质是乘累…

axios使用

Get请求 Post请求 出问题了&#xff1a; 并发请求 全局配置 多个实例如何处理 拦截器 axios在Vue中的模块封装

Install4J安装界面中如何使用脚本找到依赖程序XShell的安装位置

前言 写了一个工具, 使用Install4j打包, 但因为需要用到XShell, 所以希望在安装界面能够提前让用户配置好XShell的安装位置, 所以对Install4j的安装界面需要自定义, 后期在程序中直接过去安装位置就可以正常使用. 调研 和git-bash不一样, 安装版的XShell没有在注册表里存储安…