首页 最新 热门 推荐

  • 首页
  • 最新
  • 热门
  • 推荐

【动态规划】【树形dp】【深度优先搜索】LCP 26. 导航装置

  • 25-02-22 04:41
  • 3652
  • 11151
blog.csdn.net

本文涉及知识点

动态规划汇总

LCP 26. 导航装置

小扣参加的秋日市集景区共有 N 个景点,景点编号为 1~N。景点内设有 −1N−1 条双向道路,使所有景点形成了一个二叉树结构,根结点记为 root,景点编号即为节点值。
由于秋日市集景区的结构特殊,游客很容易迷路,主办方决定在景区的若干个景点设置导航装置,按照所在景点编号升序排列后定义装置编号为 1 ~ M。导航装置向游客发送数据,数据内容为列表 [游客与装置 1 的相对距离,游客与装置 2 的相对距离,…,游客与装置 M 的相对距离]。由于游客根据导航装置发送的信息来确认位置,因此主办方需保证游客在每个景点接收的数据信息皆不相同。请返回主办方最少需要设置多少个导航装置。
示例 1:

输入:root = [1,2,null,3,4]

输出:2

解释:在景点 1、3 或景点 1、4 或景点 3、4 设置导航装置。

在这里插入图片描述

示例 2:

输入:root = [1,2,3,4]

输出:1

解释:在景点 3、4 设置导航装置皆可。

在这里插入图片描述
提示:
2 <= N <= 50000
二叉树的非空节点值为 1~N 的一个排列。

深度优先搜索

原理

性质一:对根节点为root1的子树,将子树外的装置移到root1,效果一样。此子树任意两个节点n1,n2。装置在x,n1和n2的距离差为:(n1 → \rightarrow →root1 → \rightarrow →x)-(n2 → \rightarrow →root1 → \rightarrow →x)    ⟺    \iff ⟺ (n1 → \rightarrow →root1)-(n2 → \rightarrow →root1)    ⟺    \iff ⟺ 此装置放到root1。当前子树根节点或树外有装置简称树外装置,当前子树根节点的子孙节点有装置称树内装置。
原则一:如果装置数量相同,优先使用树外装置,树外装置点可以共用。
性质二:如果一个子树,有两个子节点,那至少需要一个树内装置。树外装置无法区分左右节点。

性质三:子树各有一个装置,无需树内装置或树外装置,整个子树符合题意。
n1,N1来自左子树,n2,N2来自右子树,N1和N2各有一个装置。反证法证明,假定来两个距离都相等。即:
。 { n 1 → p 1 → N 1 = = n 2 → r o o t 1 → N 1 到 N 1 的距离相等 n 1 → r o o t 1 → N 2 = = n 2 → p 2 → N 2 到 N 2 的距离相等

{n1→p1→N1==n2→root1→N1n1→root1→N2==n2→p2→N2到N1的距离相等到N2的距离相等{n1→p1→N1==n2→root1→N1到N1的距离相等n1→root1→N2==n2→p2→N2到N2的距离相等
{n1→p1→N1==n2→root1→N1n1→root1→N2==n2→p2→N2​到N1的距离相等到N2的距离相等​
→ { n 1 − > r o o t 1 > n 2 − > r o o t 1 n 1 − > r o o t 1 < n 2 − > r o o t 1 矛盾 \rightarrow
{n1−>root1>n2−>root1n1−>root1<n2−>root1{n1−>root1>n2−>root1n1−>root1<n2−>root1
矛盾
→{n1−>root1>n2−>root1n1−>root1<n2−>root1​矛盾

性质四:子树各有一个装置,无需树内装置或树外装置。当前子树内任意一节点n1,和当前树外任意一节点n2符合题意,N1和N2是两个装置,和n1和n2的最近公共祖先p1,p2。假定距离都相等,不失一般性n1在左枝(或root1):
∵ n 1 → p 1 → N 1 = = n 2 → r o o t 1 → N 1 到 N 1 距离相等 ∵ p 1 → N 1 < r o o t 1 → N 1 ∴ n 1 → p 1 > n 2 → r o o t 1 ∵ n 1 → r o o t 1 > = n 1 → p 1 ∴ n 1 → r o o t 1 > n 2 → r o o t 1 ∴ n 1 → r o o t 1 → N 2 > n 2 → r o o t 1 → N 2 和假定到 N 2 距离相等矛盾 \because n1 \rightarrow p1 \rightarrow N1 == n2 \rightarrow root1 \rightarrow N1 到N1距离相等\\ \because p1 \rightarrow N1 < root1 \rightarrow N1 \\ \therefore n1 \rightarrow p1 > n2 \rightarrow root1 \\ \because n1 \rightarrow root1 >= n1 \rightarrow p1 \\ \therefore n1 \rightarrow root1 > n2 \rightarrow root1\\ \therefore n1 \rightarrow root1 \rightarrow N2 > n2 \rightarrow root1 \rightarrow N2 和假定到N2距离相等矛盾 ∵n1→p1→N1==n2→root1→N1到N1距离相等∵p1→N1<root1→N1∴n1→p1>n2→root1∵n1→root1>=n1→p1∴n1→root1>n2→root1∴n1→root1→N2>n2→root1→N2和假定到N2距离相等矛盾

性质五:如果左(右)子树有一个有装置,左右子树符合题意。那么有树外装置就符合题意。
a,任意节点到root1的距离都大于0,所以root1不会和子节点到root1的距离相同。
b,n1来自左子树,n2来自右子树,n1和n2到root1距离相等。不失一般性,假定此装置在左子树节点N1。 N1和n1的公共祖先P。则n1到N1的距离为:n1 → \rightarrow →P → \rightarrow →N1 ,n2到N1的距离为:n2 → \rightarrow →root1 → \rightarrow →N1 ,有n1 N1都是左子树的节点,所以他们到P的距离小于到root1的距离。 { n 1 → P < n 1 → r o o t 1 P → N 1 < r o o t → N 1 → { n 1 到 N 1 的距离 < n 1 → r o o t 1 → N 1

{n1→P<n1→root1P→N1<root→N1{n1→P<n1→root1P→N1<root→N1
\rightarrow
{n1到N1的距离<n1→root1→N1{n1到N1的距离<n1→root1→N1
{n1→P<n1→root1P→N1<root→N1​→{n1到N1的距离<n1→root1→N1​
→ → → → → → → → → → n 1 和 n 2 到 r o o t 1 的距离相同 n 1 到 N 1 的距离 < n 2 → r o o t 1 → N 1 ( n 2 到 N 1 的距离) \Large^{n1和n2到root1的距离相同}_{\rightarrow\rightarrow\rightarrow\rightarrow\rightarrow\rightarrow\rightarrow\rightarrow\rightarrow\rightarrow} \normalsize n1到N1的距离 < n2\rightarrow root1 \rightarrow N1(n2到N1的距离) →→→→→→→→→→n1和n2到root1的距离相同​n1到N1的距离<n2→root1→N1(n2到N1的距离)
性质六:如果左(右)子树有一个有装置,左右子树符合题意。那么有树外装置,树内节点和任意节点都符合题意。n1是树内节点,n2是树外节点。N1是树内装置,N2是树外装置。n1和N1的最近公共祖先是p1,n2和N2的最近公共祖先是 p2,n2和root1的最近公共祖先p3。反证发:假定n1和n2到N1和N2的距离相同。即:
n 1 → p 1 → N 1 = = n 2 → p 3 → r o o t 1 → N 1 式子一 n 1 → r o o t 1 → N 2 = = n 2 → p 2 → N 2 式子二 式子一 → n 1 − > r o o t 1 > n 2 → p 3 → r o o t 1 n 1 → r o o t 1 → N 2 > n 2 → p 3 → r o o t 1 → N 2 大于等于 n 2 → N 2 ( n 2 直达 N 2 一定不慢与需要经过 p 3 , r o o t 1 ) n1\rightarrow p1 \rightarrow N1 == n2 \rightarrow p3 \rightarrow root1 \rightarrow N1 式子一 \\ n1 \rightarrow root1 \rightarrow N2 == n2 \rightarrow p2 \rightarrow N2 式子二\\ 式子一 \rightarrow n1->root1> n2 \rightarrow p3 \rightarrow root1 \\ n1 \rightarrow root1 \rightarrow N2 > n2 \rightarrow p3 \rightarrow root1 \rightarrow N2 \\ 大于等于 n2 \rightarrow N2(n2直达N2一定不慢与需要经过p3,root1) n1→p1→N1==n2→p3→root1→N1式子一n1→root1→N2==n2→p2→N2式子二式子一→n1−>root1>n2→p3→root1n1→root1→N2>n2→p3→root1→N2大于等于n2→N2(n2直达N2一定不慢与需要经过p3,root1)
性质七:如果左右子树皆无装置,根据性质二,需要一个树内装置。不需要树外装置。
性质八:如果只有一个孩子,且孩子没有树内装置。那说明所有子孙节点都是孤子节点。需要一个树外装置,不需要树内装置。

性质六:如果根节点和树外无装置。一个子树有多个装置,另一个子树无装置。根据性质一,无法满足题目要求。
性质五: 独子树,一个装置就可以搞定,放到叶子节点或根节点。
性质六:非独子树, 如果装置放到树外或根节点,无法区分兄弟节点。如果放到兄弟及其后代上,无法区分兄弟和祖父。树外或根节点必须放到一个,树内任意位置放一个。

处理思路

独子树,返回1。
双子节点,如果后代没有双子节点,则需要新增一个装置。正棵树的根,也要一个装置。
注意: 如果根节点是双子节点忽略,因为他没祖先,无需区分。
两种情况,可以统一为:
1+ 没有后代是双子节点的双子节点。
DFS返回两个值:b1和i2。b1表示是否需要树外节点,i2表示如果有树外节点,树内需要多少节点。
一,叶子节点返回{false,0}
二, 双子节点 并且 没有子树有装置 {true,1} 两棵子树都有双子节点。
{ 单子节点返回 t u r e , 两个子树 i 2 之和 双子节点并且两个子树都有装置 f a l s e , 两个子树 i 2 之和 双子节点并且一个子树都有装置 t r u e , 两个子树 i 2 之和 → i 12 和 i 22 分别表示左只和右支的 i 2 。可以统一为: 0 ! = i 12 ∗ i 22 , 两个子树 i 2 之和

⎧⎩⎨单子节点返回ture,两个子树i2之和双子节点并且两个子树都有装置false,两个子树i2之和双子节点并且一个子树都有装置true,两个子树i2之和{单子节点返回ture,两个子树i2之和双子节点并且两个子树都有装置false,两个子树i2之和双子节点并且一个子树都有装置true,两个子树i2之和
\\ \rightarrow i12 和i22 分别表示左只和右支的i2。可以统一为:{0!=i12*i22,两个子树i2之和} ⎩ ⎨ ⎧​单子节点返回ture,两个子树i2之和双子节点并且两个子树都有装置false,两个子树i2之和双子节点并且一个子树都有装置true,两个子树i2之和​→i12和i22分别表示左只和右支的i2。可以统一为:0!=i12∗i22,两个子树i2之和

代码

class Solution {
public:
	int navigation(TreeNode* root) {
		const auto [i11, i12] = DFS(root->left);
		const auto [i21, i22] = DFS(root->right);
		if (0 == i12 + i22)
		{
			return 1;
		}
        bool b1 = (i11| i21)&&(0==i12*i22);   
		return  i12 + i22 +b1 ;
	}
	std::pair<bool, int> DFS(TreeNode* root)
	{
		if (nullptr == root)
		{
			return { 0,0 };
		}
		const auto [i11, i12] = DFS(root->left);
		const auto [i21, i22] = DFS(root->right);
		const int iChildCount = i12 + i22;
		bool b2 = (nullptr != root->left) && (nullptr != root->right);
		if (b2)
		{
			return { 0 == i12 * i22,(b2 && (0 == iChildCount)) ? 1 : iChildCount };
		}
		return { i11 | i21, iChildCount };
	}

};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30

扩展阅读

视频课程

有效学习:明确的目标 及时的反馈 拉伸区(难度合适),可以先学简单的课程,请移步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++**实现。

文章知识点与官方知识档案匹配,可进一步学习相关知识
算法技能树首页概览60496 人正在系统学习中
群中有博文配套源码
QQ群名片
注:本文转载自blog.csdn.net的闻缺陷则喜何志丹的文章"https://blog.csdn.net/he_zhidan/article/details/136052118"。版权归原作者所有,此博客不拥有其著作权,亦不承担相应法律责任。如有侵权,请联系我们删除。
复制链接
复制链接
相关推荐
发表评论
登录后才能发表评论和回复 注册

/ 登录

评论记录:

未查询到任何数据!
回复评论:

分类栏目

后端 (14832) 前端 (14280) 移动开发 (3760) 编程语言 (3851) Java (3904) Python (3298) 人工智能 (10119) AIGC (2810) 大数据 (3499) 数据库 (3945) 数据结构与算法 (3757) 音视频 (2669) 云原生 (3145) 云平台 (2965) 前沿技术 (2993) 开源 (2160) 小程序 (2860) 运维 (2533) 服务器 (2698) 操作系统 (2325) 硬件开发 (2492) 嵌入式 (2955) 微软技术 (2769) 软件工程 (2056) 测试 (2865) 网络空间安全 (2948) 网络与通信 (2797) 用户体验设计 (2592) 学习和成长 (2593) 搜索 (2744) 开发工具 (7108) 游戏 (2829) HarmonyOS (2935) 区块链 (2782) 数学 (3112) 3C硬件 (2759) 资讯 (2909) Android (4709) iOS (1850) 代码人生 (3043) 阅读 (2841)

热门文章

101
推荐
关于我们 隐私政策 免责声明 联系我们
Copyright © 2020-2025 蚁人论坛 (iYenn.com) All Rights Reserved.
Scroll to Top