【深度优先搜索】【C++算法】834 树中距离之和

2024-01-26 10:52

本文主要是介绍【深度优先搜索】【C++算法】834 树中距离之和,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

作者推荐

【动态规划】【map】【C++算法】1289. 下降路径最小和 II

本文涉及知识点

深度优先搜索 树 图论

LeetCode834 树中距离之和

给定一个无向、连通的树。树中有 n 个标记为 0…n-1 的节点以及 n-1 条边 。
给定整数 n 和数组 edges , edges[i] = [ai, bi]表示树中的节点 ai 和 bi 之间有一条边。
返回长度为 n 的数组 answer ,其中 answer[i] 是树中第 i 个节点与所有其他节点之间的距离之和。
示例 1:
输入: n = 6, edges = [[0,1],[0,2],[2,3],[2,4],[2,5]]
输出: [8,12,6,10,10,10]
解释: 树如图所示。
我们可以计算出 dist(0,1) + dist(0,2) + dist(0,3) + dist(0,4) + dist(0,5)
也就是 1 + 1 + 2 + 2 + 2 = 8。 因此,answer[0] = 8,以此类推。
示例 2:
输入: n = 1, edges = []
输出: [0]
示例 3:
输入: n = 2, edges = [[1,0]]
输出: [1,1]
参数:
1 <= n <= 3 * 104
edges.length == n - 1
edges[i].length == 2
0 <= ai, bi < n
ai != bi
给定的输入保证为有效的树

深度优先搜索

假定节点0是树的根。
一,通过深度优先搜索计算m_vSubNodeCounts[i] ,以i为根节点的子树的节点数量。
二,通过深度优先搜索计算0到所有节点的距离。
DFSDis返回值是: cur到所有子孙节点的距离。
三,深度优先搜索,通过父节点到各点距离,计算当前节点到各点距离。
当前节点 和 当前节点的子孙节点 到 当前节点 的距离比到当前节点的父节点少1。
其它节点 到当前节点的距离比到当前节点的父节点的距离多1。

代码

核心代码

class CNeiBo2
{
public:CNeiBo2(int n, bool bDirect, int iBase = 0) :m_iN(n), m_bDirect(bDirect), m_iBase(iBase){m_vNeiB.resize(n);}CNeiBo2(int n, vector<vector<int>>& edges, bool bDirect, int iBase = 0) :m_iN(n), m_bDirect(bDirect), m_iBase(iBase){m_vNeiB.resize(n);for (const auto& v : edges){m_vNeiB[v[0] - iBase].emplace_back(v[1] - iBase);if (!bDirect){m_vNeiB[v[1] - iBase].emplace_back(v[0] - iBase);}}}inline void Add(int iNode1, int iNode2){iNode1 -= m_iBase;iNode2 -= m_iBase;m_vNeiB[iNode1].emplace_back(iNode2);if (!m_bDirect){m_vNeiB[iNode2].emplace_back(iNode1);}}const int m_iN;const bool m_bDirect;const int m_iBase;vector<vector<int>> m_vNeiB;
};class Solution {
public:vector<int> sumOfDistancesInTree(int n, vector<vector<int>>& edges) {m_vSubNodeCounts.resize(n);m_vRet.resize(n);CNeiBo2 neiBo(n, edges, false);DFSSubNodeCount(neiBo, 0, -1);m_vRet[0] = DFSDis(neiBo, 0, -1);DFS(neiBo, 0, -1);return m_vRet;}void DFS(const CNeiBo2& neiBo, int cur, int parent){if (-1 != parent){m_vRet[cur] = m_vRet[parent] - m_vSubNodeCounts[cur] + (m_vSubNodeCounts.size() - m_vSubNodeCounts[cur]);}for (const auto& next : neiBo.m_vNeiB[cur]){if (parent == next){continue;}DFS(neiBo, next, cur);}}int DFSSubNodeCount(const CNeiBo2& neiBo,int cur,int parent){int iRet = 1;for (const auto& next : neiBo.m_vNeiB[cur]){if (parent == next){continue;}iRet += DFSSubNodeCount(neiBo, next, cur);}return m_vSubNodeCounts[cur] = iRet;}int DFSDis(const CNeiBo2& neiBo, int cur, int parent)	{int iDis = m_vSubNodeCounts[cur]-1;for (const auto& next : neiBo.m_vNeiB[cur]){if (parent == next){continue;}iDis += DFSDis(neiBo, next, cur);}return iDis;}vector<int> m_vSubNodeCounts,m_vRet;
};

测试用例

template<class T>
void Assert(const T& t1, const T& t2)
{assert(t1 == t2);
}template<class T>
void Assert(const vector<T>& v1, const vector<T>& v2)
{if (v1.size() != v2.size()){assert(false);return;}for (int i = 0; i < v1.size(); i++){Assert(v1[i], v2[i]);}}int main()
{int n;vector<vector<int>> edges;{Solution sln;n = 6, edges = { {0,1},{0,2},{2,3},{2,4},{2,5} };auto res = sln.sumOfDistancesInTree(n, edges);Assert(vector<int>{8, 12, 6, 10, 10, 10}, res);}{Solution sln;n = 1, edges = {};auto res = sln.sumOfDistancesInTree(n, edges);Assert(vector<int>{0}, res);}{Solution sln;n = 2, edges = { {1,0} };auto res = sln.sumOfDistancesInTree(n, edges);Assert(vector<int>{1,1}, res);}{Solution sln;n = 3, edges = { {2,1},{0,2} };auto res = sln.sumOfDistancesInTree(n, edges);Assert(vector<int>{3,3,2}, res);}
}

2023年1月

class Solution {
public:
vector sumOfDistancesInTree(int n, vector<vector>& edges) {
m_n = n;
m_vChildDis.assign(n, -1);
m_vChildNum.resize(n, -1);
m_vNP.resize(n);
m_vTotalNum.resize(n);
for (auto& e : edges)
{
m_vNP[e[0]].push_back(e[1]);
m_vNP[e[1]].push_back(e[0]);
}
dfs1(0, -1);
dfs2(0, -1);
return m_vTotalNum;
}
void dfs1(int iCur, const int iParent)
{
int iDis = 0;
int iNum = 0;
for (const auto& next : m_vNP[iCur])
{
if (iParent == next)
{
continue;
}
dfs1(next, iCur);
iDis += m_vChildDis[next];
iNum += m_vChildNum[next];
}
m_vChildDis[iCur] = iDis + iNum;
m_vChildNum[iCur] = iNum+1;
}
void dfs2(int iCur, const int iParent)
{
if (-1 == iParent)
{
m_vTotalNum[iCur] = m_vChildDis[iCur];
}
else
{
m_vTotalNum[iCur] = m_vTotalNum[iParent] - m_vChildDis[iCur] - m_vChildNum[iCur] + (m_n - m_vChildNum[iCur]) + m_vChildDis[iCur];
}
for (const auto& next : m_vNP[iCur])
{
if (iParent == next)
{
continue;
}
dfs2(next, iCur);
}
}
vector m_vChildDis;//距离子孙节点之和
vector m_vChildNum;//子孙数量之和+1
vector m_vTotalNum;
int m_n;
vector < vector > m_vNP;
};

2023年 6月

class Solution {
public:
vector sumOfDistancesInTree(int n, vector<vector>& edges) {
m_vTotalDis.resize(n);
m_vNodeNum.resize(n);
m_vLeve.resize(n);
m_vParent.assign(n, -1);
CNeiBo2 neiBo(n, edges, false);
DSFLeveAndNodeCount(neiBo.m_vNeiB, 0, -1);
m_vTotalDis[0] = std::accumulate(m_vLeve.begin(), m_vLeve.end(), 0);
//必须按父子顺序出来
DFS(neiBo.m_vNeiB, 0, -1);
return m_vTotalDis;
}
void DFS(vector<vector>& neiBo, int iCur, int iParent)
{
if (-1 != iParent)
{
m_vTotalDis[iCur] = m_vTotalDis[m_vParent[iCur]] - m_vNodeNum[iCur] + (m_vNodeNum[0] - m_vNodeNum[iCur]);
}
for (const auto& next : neiBo[iCur])
{
if (next == iParent)
{
continue;
}
DFS(neiBo, next, iCur);
}
}
void DSFLeveAndNodeCount( vector<vector>& neiBo,int iCur,int iParent)
{
if (-1 != iParent)
{
m_vLeve[iCur] = m_vLeve[iParent] + 1;
m_vParent[iCur] = iParent;
}
m_vNodeNum[iCur] = 1;
for (const auto& next : neiBo[iCur])
{
if (next == iParent)
{
continue;
}
DSFLeveAndNodeCount(neiBo,next, iCur);
m_vNodeNum[iCur] += m_vNodeNum[next];
}
}
vector m_vTotalDis,m_vNodeNum,m_vLeve,m_vParent;
};

扩展阅读

视频课程

有效学习:明确的目标 及时的反馈 拉伸区(难度合适),可以先学简单的课程,请移步CSDN学院,听白银讲师(也就是鄙人)的讲解。
https://edu.csdn.net/course/detail/38771

如何你想快

速形成战斗了,为老板分忧,请学习C#入职培训、C++入职培训等课程
https://edu.csdn.net/lecturer/6176

相关

下载

想高屋建瓴的学习算法,请下载《喜缺全书算法册》doc版
https://download.csdn.net/download/he_zhidan/88348653

我想对大家说的话
闻缺陷则喜是一个美好的愿望,早发现问题,早修改问题,给老板节约钱。
子墨子言之:事无终始,无务多业。也就是我们常说的专业的人做专业的事。
如果程序是一条龙,那算法就是他的是睛

测试环境

操作系统:win7 开发环境: VS2019 C++17
或者 操作系统:win10 开发环境: VS2022 C++17
如无特殊说明,本算法用**C++**实现。

这篇关于【深度优先搜索】【C++算法】834 树中距离之和的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/646565

相关文章

不懂推荐算法也能设计推荐系统

本文以商业化应用推荐为例,告诉我们不懂推荐算法的产品,也能从产品侧出发, 设计出一款不错的推荐系统。 相信很多新手产品,看到算法二字,多是懵圈的。 什么排序算法、最短路径等都是相对传统的算法(注:传统是指科班出身的产品都会接触过)。但对于推荐算法,多数产品对着网上搜到的资源,都会无从下手。特别当某些推荐算法 和 “AI”扯上关系后,更是加大了理解的难度。 但,不了解推荐算法,就无法做推荐系

康拓展开(hash算法中会用到)

康拓展开是一个全排列到一个自然数的双射(也就是某个全排列与某个自然数一一对应) 公式: X=a[n]*(n-1)!+a[n-1]*(n-2)!+...+a[i]*(i-1)!+...+a[1]*0! 其中,a[i]为整数,并且0<=a[i]<i,1<=i<=n。(a[i]在不同应用中的含义不同); 典型应用: 计算当前排列在所有由小到大全排列中的顺序,也就是说求当前排列是第

认识、理解、分类——acm之搜索

普通搜索方法有两种:1、广度优先搜索;2、深度优先搜索; 更多搜索方法: 3、双向广度优先搜索; 4、启发式搜索(包括A*算法等); 搜索通常会用到的知识点:状态压缩(位压缩,利用hash思想压缩)。

hdu1240、hdu1253(三维搜索题)

1、从后往前输入,(x,y,z); 2、从下往上输入,(y , z, x); 3、从左往右输入,(z,x,y); hdu1240代码如下: #include<iostream>#include<algorithm>#include<string>#include<stack>#include<queue>#include<map>#include<stdio.h>#inc

hdu1180(广搜+优先队列)

此题要求最少到达目标点T的最短时间,所以我选择了广度优先搜索,并且要用到优先队列。 另外此题注意点较多,比如说可以在某个点停留,我wa了好多两次,就是因为忽略了这一点,然后参考了大神的思想,然后经过反复修改才AC的 这是我的代码 #include<iostream>#include<algorithm>#include<string>#include<stack>#include<

【C++ Primer Plus习题】13.4

大家好,这里是国中之林! ❥前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站。有兴趣的可以点点进去看看← 问题: 解答: main.cpp #include <iostream>#include "port.h"int main() {Port p1;Port p2("Abc", "Bcc", 30);std::cout <<

csu 1446 Problem J Modified LCS (扩展欧几里得算法的简单应用)

这是一道扩展欧几里得算法的简单应用题,这题是在湖南多校训练赛中队友ac的一道题,在比赛之后请教了队友,然后自己把它a掉 这也是自己独自做扩展欧几里得算法的题目 题意:把题意转变下就变成了:求d1*x - d2*y = f2 - f1的解,很明显用exgcd来解 下面介绍一下exgcd的一些知识点:求ax + by = c的解 一、首先求ax + by = gcd(a,b)的解 这个

C++包装器

包装器 在 C++ 中,“包装器”通常指的是一种设计模式或编程技巧,用于封装其他代码或对象,使其更易于使用、管理或扩展。包装器的概念在编程中非常普遍,可以用于函数、类、库等多个方面。下面是几个常见的 “包装器” 类型: 1. 函数包装器 函数包装器用于封装一个或多个函数,使其接口更统一或更便于调用。例如,std::function 是一个通用的函数包装器,它可以存储任意可调用对象(函数、函数

综合安防管理平台LntonAIServer视频监控汇聚抖动检测算法优势

LntonAIServer视频质量诊断功能中的抖动检测是一个专门针对视频稳定性进行分析的功能。抖动通常是指视频帧之间的不必要运动,这种运动可能是由于摄像机的移动、传输中的错误或编解码问题导致的。抖动检测对于确保视频内容的平滑性和观看体验至关重要。 优势 1. 提高图像质量 - 清晰度提升:减少抖动,提高图像的清晰度和细节表现力,使得监控画面更加真实可信。 - 细节增强:在低光条件下,抖

C++11第三弹:lambda表达式 | 新的类功能 | 模板的可变参数

🌈个人主页: 南桥几晴秋 🌈C++专栏: 南桥谈C++ 🌈C语言专栏: C语言学习系列 🌈Linux学习专栏: 南桥谈Linux 🌈数据结构学习专栏: 数据结构杂谈 🌈数据库学习专栏: 南桥谈MySQL 🌈Qt学习专栏: 南桥谈Qt 🌈菜鸡代码练习: 练习随想记录 🌈git学习: 南桥谈Git 🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈�