当前位置: 首页 > news >正文

每日算法刷题Day78:10.23:leetcode 一般树7道题,用时1h30min

1.建立二叉搜索树:
(1)父子关系表
输入格式:

5
0 2    (节点0是根,子节点是2)
2 1    (节点2子节点是1)
2 3    (节点2子节点是3)
1 4    (节点1子节点是4)
3 5    (节点3子节点是5)

建立一般树:

vector<vector<int>> g; // 邻接表
// 带权值
// typedef pair<int,int> PII;
// vector<vector<PII>> g;
void bulidTree(){int n;cin>>n;for(int i=0;i<n;++i){int a,b;cin>>a>>b;g[a].push_back(b);// g[b].push_back(a); // 无向树}
}

DFS遍历二叉树(需传递父节点,防止回头,树无回路,所以无需vis数组):

void dfs(int cur,int fa){for(auto& nxt:g[cur]){if(nxt==fa) continue;dfs(nxt,cur);}
}

一、遍历

1.套路
2.题目描述
3.学习经验
1. 2368.受限条件下可到达节点的数目(中等,学习优化思想)

2368. 受限条件下可到达节点的数目 - 力扣(LeetCode)

思想

1.现有一棵由 n 个节点组成的无向树,节点编号从 0 到 n - 1 ,共有 n - 1 条边。
给你一个二维整数数组 edges ,长度为 n - 1 ,其中 edges[i] = [ai, bi] 表示树中节点 ai 和 bi 之间存在一条边。另给你一个整数数组 restricted 表示 受限 节点。
在不访问受限节点的前提下,返回你可以从节点 0 到达的 最多 节点数目_。_
注意,节点 0  会标记为受限节点。
2.我的思路是在dfs遍历时判断是否受限,但这样会增加遍历次数
3.优化思想是在建树时就判断是否受限,若两端都不受限才建立边
4.然后节点数目可以不用vis数组,而是递归返回

代码
class Solution {
public:vector<vector<int>> g;int res = 0;set<int> st;vector<bool> vis;void dfs(int cur, int fa) {if (!vis[cur]) {++res;vis[cur] = true;}for (auto& nxt : g[cur]) {if (nxt == fa || st.count(nxt))continue;dfs(nxt, cur);}}int reachableNodes(int n, vector<vector<int>>& edges,vector<int>& restricted) {g.resize(n);for (auto& e : edges) {int a = e[0], b = e[1];g[a].push_back(b);g[b].push_back(a);}for (int& x : restricted)st.insert(x);vis.assign(n, false);dfs(0, -1);return res;}
};

优化代码:

class Solution {
public:vector<vector<int>> g;int res = 0;set<int> st;vector<bool> vis;int dfs(int cur, int fa) {int cnt=1;for (auto& nxt : g[cur]) {if (nxt == fa)continue;cnt+=dfs(nxt, cur);}return cnt;}int reachableNodes(int n, vector<vector<int>>& edges,vector<int>& restricted) {g.resize(n);for (int& x : restricted)st.insert(x);for (auto& e : edges) {int a = e[0], b = e[1];if(!st.count(a) && !st.count(b)){ // 建树时判断g[a].push_back(b);g[b].push_back(a);}}return dfs(0, -1);}
};
2. 1466. 重新规划路线(中等)

1466. 重新规划路线 - 力扣(LeetCode)

思想

1.n 座城市,从 0 到 n-1 编号,其间共有 n-1 条路线。因此,要想在两座不同城市之间旅行只有唯一一条路线可供选择(路线网形成一颗树)。去年,交通运输部决定重新规划路线,以改变交通拥堵的状况。
路线用 connections 表示,其中 connections[i] = [a, b] 表示从城市 a 到 b 的一条有向路线。
今年,城市 0 将会举办一场大型比赛,很多游客都想前往城市 0 。
请你帮助重新规划路线方向,使每个城市都可以访问城市 0 。返回需要变更方向的最小路线数。
题目数据 保证 每个城市在重新规划路线方向后都能到达城市 0 。

代码
class Solution {
public:vector<vector<int>> gIn, gOut;int res = 0;void dfs(int cur, int fa) {for (auto& nxt : gOut[cur]) {if (nxt == fa)continue;++res;dfs(nxt, cur);}for (auto& nxt : gIn[cur]) {if (nxt == fa)continue;dfs(nxt, cur);}}int minReorder(int n, vector<vector<int>>& connections) {gIn.resize(n);gOut.resize(n);for (auto& con : connections) {int a = con[0], b = con[1];gOut[a].push_back(b);gIn[b].push_back(a);}dfs(0, -1);return res;}
};

二、自顶向下DFS

1.套路
2.题目描述
3.学习经验
1. 1376. 通知所有员工所需的时间(中等)

1376. 通知所有员工所需的时间 - 力扣(LeetCode)

思想

1.公司里有 n 名员工,每个员工的 ID 都是独一无二的,编号从 0 到 n - 1。公司的总负责人通过 headID 进行标识。
在 manager 数组中,每个员工都有一个直属负责人,其中 manager[i] 是第 i 名员工的直属负责人。对于总负责人,manager[headID] = -1。题目保证从属关系可以用树结构显示。
公司总负责人想要向公司所有员工通告一条紧急消息。他将会首先通知他的直属下属们,然后由这些下属通知他们的下属,直到所有的员工都得知这条紧急消息。
第 i 名员工需要 informTime[i] 分钟来通知它的所有直属下属(也就是说在 informTime[i] 分钟后,他的所有直属下属都可以开始传播这一消息)。
返回通知所有员工这一紧急消息所需要的 分钟数 。

代码
class Solution {
public:vector<vector<int>> g;int res = 0;void dfs(int cur, int fa, int sumTime, vector<int>& informTime) {res = max(res, sumTime);sumTime += informTime[cur];for (auto& nxt : g[cur]) {if (nxt == fa)continue;dfs(nxt, cur, sumTime, informTime);}}int numOfMinutes(int n, int headID, vector<int>& manager,vector<int>& informTime) {g.resize(n);for (int i = 0; i < n; ++i) {// ma[i]->iif (manager[i] != -1)g[manager[i]].push_back(i);}dfs(headID, -1, 0, informTime);return res;}
};
2. 3528. 单位转换I(中等)

3528. 单位转换 I - 力扣(LeetCode)

思想

1.有 n 种单位,编号从 0 到 n - 1。给你一个二维整数数组 conversions,长度为 n - 1,其中 conversions[i] = [sourceUniti, targetUniti, conversionFactori] ,表示一个 sourceUniti 类型的单位等于 conversionFactori 个 targetUniti 类型的单位。
请你返回一个长度为 n 的数组 baseUnitConversion,其中 baseUnitConversion[i] 表示 一个 0 类型单位等于多少个 i 类型单位。由于结果可能很大,请返回每个 baseUnitConversion[i] 对 109 + 7 取模后的值。

代码
class Solution {
public:typedef pair<int, int> PII;vector<vector<PII>> g;vector<int> res;int n;const int mod = 1e9 + 7;typedef long long ll;void dfs(int cur, int fa, ll ji) {res[cur] = ji % mod;for (auto& nxt : g[cur]) {int nxtTar = nxt.first, nxtFac = nxt.second;if (nxtTar == fa)continue;dfs(nxtTar, cur, ji * nxtFac % mod);}}vector<int> baseUnitConversions(vector<vector<int>>& conversions) {n = conversions.size() + 1;g.resize(n);res.resize(n);for (auto& con : conversions) {int sou = con[0], tar = con[1], fac = con[2];g[sou].push_back({tar, fac});}dfs(0, -1, 1);return res;}
};
3. 1443. 收集树上所有苹果的最少时间(中等)

1443. 收集树上所有苹果的最少时间 - 力扣(LeetCode)

思想

1.给你一棵有 n 个节点的无向树,节点编号为 0 到 n-1 ,它们中有一些节点有苹果。通过树上的一条边,需要花费 1 秒钟。你从 节点 0 出发,请你返回最少需要多少秒,可以收集到所有苹果,并回到节点 0 。
无向树的边由 edges 给出,其中 edges[i] = [fromi, toi] ,表示有一条边连接 from 和 toi 。除此以外,还有一个布尔数组 hasApple ,其中 hasApple[i] = true 代表节点 i 有一个苹果,否则,节点 i 没有苹果。

代码
class Solution {
public:vector<vector<int>> g;typedef pair<int, bool> PIO;PIO dfs(int cur,int fa, vector<bool>& hasApple) {int cnt = 0;bool isA = false;for (auto& nxt : g[cur]) {if(nxt==fa) continue;auto tmp = dfs(nxt,cur, hasApple);if (tmp.second) {cnt += tmp.first + 2;isA = true;}}if (hasApple[cur])isA = true;return {cnt, isA};}int minTime(int n, vector<vector<int>>& edges, vector<bool>& hasApple) {g.resize(n);for (auto& e : edges) {int a = e[0], b = e[1];g[a].push_back(b);g[b].push_back(a);}auto tmp = dfs(0,-1, hasApple);return tmp.first;}
};

三、自底向上DFS

1.套路
2.题目描述
3.学习经验
1. 690. 员工的重要性(中等)

690. 员工的重要性 - 力扣(LeetCode)

思想

1.你有一个保存员工信息的数据结构,它包含了员工唯一的 id ,重要度和直系下属的 id 。
给定一个员工数组 employees,其中:

  • employees[i].id 是第 i 个员工的 ID。
  • employees[i].importance 是第 i 个员工的重要度。
  • employees[i].subordinates 是第 i 名员工的直接下属的 ID 列表。
    给定一个整数 id 表示一个员工的 ID,返回这个员工和他所有下属的重要度的 总和
    2.注意:
auto emp = mp[id];

这里如果id不存在,就会尝试插入一个默认构造的值,所以结构体得有默认构造,不能只有显式构造

代码
/*
// Definition for Employee.
class Employee {
public:int id;int importance;vector<int> subordinates;
};
*/class Solution {
public:struct newEmployee {int importance;vector<int> subordinates;// 得有默认构造newEmployee() : importance(0), subordinates() {}newEmployee(int _imp, vector<int> _sub): importance(_imp), subordinates(_sub) {}};map<int, newEmployee> mp;int dfs(int id) {int sum = 0;auto emp = mp[id];for (auto& nxt : emp.subordinates) {sum += dfs(nxt);}sum += emp.importance;return sum;}int getImportance(vector<Employee*> employees, int id) {for (auto& emp : employees) {mp[emp->id] = newEmployee(emp->importance, emp->subordinates);}return dfs(id);}
};
2. 3249. 统计好节点的数目(中等)

3249. 统计好节点的数目 - 力扣(LeetCode)

思想

1.现有一棵 无向 树,树中包含 n 个节点,按从 0 到 n - 1 标记。树的根节点是节点 0 。给你一个长度为 n - 1 的二维整数数组 edges,其中 edges[i] = [ai, bi] 表示树中节点 ai 与节点 bi 之间存在一条边。
如果一个节点的所有子节点为根的 子树 包含的节点数相同,则认为该节点是一个 好节点
返回给定树中 好节点 的数量。
子树 指的是一个节点以及它所有后代节点构成的一棵树。

代码
class Solution {
public:vector<vector<int>> g;int n;int res = 0;int dfs(int cur, int fa) {int pre = INT_MIN;bool isG = true;int sum = 1;for (auto& nxt : g[cur]) {if (nxt == fa)continue;int cnt = dfs(nxt, cur);sum += cnt;if (pre == INT_MIN)pre = cnt;else if (pre != cnt)isG = false;}if (isG)++res;return sum;}int countGoodNodes(vector<vector<int>>& edges) {n = edges.size() + 1;g.resize(n);for (auto& e : edges) {int a = e[0], b = e[1];g[a].push_back(b);g[b].push_back(a);}dfs(0, -1);return res;}
};
http://www.dtcms.com/a/520125.html

相关文章:

  • 薄膜测厚选CWL法还是触针法?针对不同厚度与材质的台阶仪技术选型指南
  • WPF-MVVM的简单入门(第一个MVVM程序)
  • blender拓扑建模教程
  • asp.net手机网站开发教程翻译网站建设方案
  • 佛山建设网站公司哪家好特斯拉ceo进厂拧螺丝
  • 如何做新网站保留域名wordpress基础
  • C# 实现 Modbus TCP 通信
  • 《Git:从入门到精通(七)——Git分支管理与协作开发实战》
  • 超越传统工具:利用Reddit发现关键词的独特视角与前沿方法
  • 数据结构——二叉搜索树深度解析
  • macOS 无法在根目录创建目录的原因与解决方案
  • 11.23 鸿蒙HTTP数据请求
  • 郑州网站建设最低价网址导航的意思
  • LOESS回归
  • 跨平台开发中的图形渲染:Canvas与View+CSS的性能分析与决策路径
  • 能源经济选题推荐:可再生能源转型政策如何提高能源韧性?基于双重机器学习的因果推断
  • 《R for Data Science (2e)》免费中文翻译 (第11章) --- Communication(1)
  • 生成式对抗网络 GAN:从零理解生成对抗网络的原理与魅力
  • 李宏毅机器学习笔记30
  • 做塑胶材料的网站深圳网站设计平台
  • 【设计模式】装饰器模式(Decorator)
  • 设计模式之:享元模式
  • android 图像显示框架二——流程分析
  • CentOS 10 系统安装
  • MySQL试验部署
  • 【文献笔记】ICLR 2018 | Graph Attention Networks
  • Day69 SQLite3动态库移植 + BMP图像解析显示 + 进度条控件设计与动态文本管理
  • 通过自构建的时间服务器主机给客户端主机同步时间
  • [特殊字符] 软考架构师 vs. 考研408:全方位对比
  • C语言进阶:(一)深度剖析函数栈帧:从创建到销毁