2023-07-16 LeetCode每日一题(树中距离之和)

news/2024/11/19 15:12:48/

2023-07-16每日一题

一、题目编号

834. 树中距离之和

二、题目链接

点击跳转到题目位置

三、题目描述

给定一个无向、连通的树。树中有 n 个标记为 0…n-1 的节点以及 n-1 条边 。

给定整数 n 和数组 edges , edges[i] = [ai, bi]表示树中的节点 ai 和 bi 之间有一条边。

返回长度为 n 的数组 answer ,其中 answer[i] 是树中第 i 个节点与所有其他节点之间的距离之和。

提示:

  • 1 <= n <= 3 * 104
  • edges.length == n - 1
  • edges[i].length == 2
  • 0 <= ai, bi < n
  • ai != bi
  • 给定的输入保证为有效的树

四、解题代码

class Solution {int dp[30004];//表示dp[u] 表示以u为根的子树,它的所有子节点到它的距离之和int sz[30004];//表示以u为根的子树的节点数量vector<int> ans;//表示最终的答案vector<int>Edge[30004];void dfs1(int u, int f) {sz[u] = 1;dp[u] = 0;for (int i = 0; i < Edge[u].size(); ++i) {int v = Edge[u][i];if (v == f) {continue;}dfs1(v, u);dp[u] += dp[v] + sz[v];sz[u] += sz[v];}}void dfs2(int u, int f) {ans[u] = dp[u];for (int i = 0; i < Edge[u].size(); ++i) {int v = Edge[u][i];if (v == f) {continue;}int pu = dp[u], pv = dp[v];int su = sz[u], sv = sz[v];dp[u] -= dp[v] + sz[v];sz[u] -= sz[v];dp[v] += dp[u] + sz[u];sz[v] += sz[u];dfs2(v, u);dp[u] = pu, dp[v] = pv;sz[u] = su, sz[v] = sv;}}public:vector<int> sumOfDistancesInTree(int n, vector<vector<int>>& edges) {for(int i = 0; i < n; ++i){Edge[i].clear();}for(int i = 0; i < n - 1; ++i){int x = edges[i][0];int y = edges[i][1]; Edge[x].push_back(y);Edge[y].push_back(x);}memset(dp, 0, sizeof(dp));memset(sz, 0, sizeof(sz));ans.resize(n);dfs1(0, -1);dfs2(0, -1);return ans;}
};

五、解题思路

(1) 采用树型dp来解决该问题。

(2) 先设置初始状态,dp[u] 表示以u为根的子树,它的所有子节点到它的距离之和。sz[u]表示以u为根的子树的节点数量。vector ans表示最终答案。

(3) 那么需要问一个问题,我们所需要求的是dp[u]是怎么得到的。节点u有x1,x2,x3个子节点,那么dp[u]就应当等于3+dp[x1]+dp[x2]+dp[x3]。那么sz[u]表示sz[x1] + sz[x2] + sz[x3],这个是dfs1中所完成的工作。当然一开始所有的sz都应该为1。我们按照这样的思路进行n次,那么一定能解决问题,但是时间复杂度很高,能不能优化呢。

(4) 经过一次树形动态规划后其实我们获得了在 u 为根的树中,每个节点为根的子树的答案 dp,我们可以利用这些已有信息来优化时间复杂度。本来我们所求的是以u为根节点,v为子节点,后面我们要进行置换一下,那么v是根节点,u为子节点了。除了dp[u]和dp[v]的值,其他的值并不需要变化。首先u要减去v的贡献。v要加上u的贡献。这样我们便实现了换根的操作了。


http://www.ppmy.cn/news/911909.html

相关文章

linux系统优化设置及软件集合

说明:部分条目没有实践,同时有一些重复的内容,以后改进. 1.更快速的打开网页&#xff0c;在firefox浏览器地址拦里输入about:config 找下面的选项进行修改吧: network.dns.disableIPv6 -> true network.http.pipelining -> true network.http.pipelining.maxrequests -&g…

ubuntu专辑

nl filename |tee filename.out 在filename内容前加行号 或者在vim中直接执行 :%!nl 之后使用vim的多行编辑方式,将多余的行首空格删掉 :%s *$ 将所有行尾多余的空格删除 使用gedit打印filename,在打印选项中,选择打印行号也可以,gedit还可以选择语法高亮是否打印. luth…

ubuntu linux环境使用技巧

ubuntu linux环境使用技巧 2010年07月28日 0) 什么是wubi安装&#xff1f;wubi安装有哪些注意事项&#xff1f; 所谓wubi就是指windows下的ubuntu安装程序(Ubuntu installer for Windows)。注意尽量选择在ntfs分区上安装&#xff0c;这样可以避免若干问题&#xff08;如下述&a…

邮件服务器

邮件服务器 邮件服务器的功能与运作原理:他是利用网络传递一些信息给远程服务器的一种信息传递行为,相当具有时效性,不过现在有很多人乱用,导致垃圾信件,色情,广告信件等等 的滥用,时至今日,Google和几个大型的网络公司都有提供免费或者付费的邮件服务器,除非必要,…

第二十二章、邮件服务器: Postfix

在这个邮件服务器的架设中&#xff0c;我们首先谈论 Mail 与 DNS 的重要相关性&#xff0c;然后依序介绍 Mail Server 的相关名词&#xff0c;以及 Mail Server 的运作基本流程与协议&#xff0c;也会谈到相关的 Relay 与邮件认证机制等项目&#xff0c; 这些项目对于未来邮件服…

鸟哥的Linux私房菜(服务器)- 第二十二章、邮件服务器: Postfix

第二十二章、邮件服务器&#xff1a; Postfix 最近更新日期&#xff1a;2011/08/10 在这个邮件服务器的架设中&#xff0c;我们首先谈论 Mail 与 DNS 的重要相关性&#xff0c;然后依序介绍 Mail Server 的相关名词&#xff0c;以及 Mail Server 的运作基本流程与协议&#xff…

学 Vim 时希望早点知道的建议

从 2009 年开始&#xff0c;我就一直把 Vim 当做我的主要&#xff08;唯一&#xff09;文本编辑器。在过去的这些年&#xff0c;我学到了很多好用的 Vim 技巧&#xff0c;它们令我感觉相见恨晚&#xff0c;因为它们极大地提高了我的文本编辑效率。在这篇博文中&#xff0c;我想…

vim 操作

vim -b test.bin vim 的 -b 选项是告诉 vim 打开的是一个二进制文件&#xff0c;不指定的话&#xff0c;会在后面加上 0x0a &#xff0c;即一个换行符&#xff0c;这样若是二进制文件&#xff0c;则文件被改变了&#xff0c;后面多了一个0x0a。 命令行模式下&#xff1a; :%!xx…