【C++算法】树的最长同值路径

问题

给定⼀个⼆叉树,找到最⻓的路径,这个路径中的每个节点具有相同数值。 这条路径可以经过也可以不经过根节点。 注意:两个节点之间的路径⻓度由它们之间的边数表示。

示例:

       输入:

       输出:最长路径的元素是5

                     其长度是3

分析

分析一下题目,其实就是要找一个二叉树内具有相同的值的节点的最长路径,我们可以从根节点开始,逐步往下遍历,寻找相同的值的节点的最长路径,因此,这道题是一个很明显的深度优先搜索DFS的题目。

       DFS的题目需要用到递归的知识,因此我们考虑两个方面:终止条件和函数执行体。因为是深度优先搜索,所以很明显终止条件是搜索到叶子节点的时候就停止递归搜索。而如何进行写函数执行体,我们需要考虑两个方面,一个是两个节点的值是否相同,一个是两个节点是否连续。

       这里要避开两个错误思路。

一个是判断两个节点的值是否相同的时候,只使用了一个变量去记录,如果相同就保持变量不变,记录下这个值是多少,如果不同就更新这个值。这个思路是错误的,因为你在DFS的时候,是先搜索完左子树,然后再回溯搜索右子树的,所以可能你根节点和左子树根节点值不同,但是和右子树根节点值相同,但是当你搜索到右子树的时候,那个变量的值已经被你搜索左子树的时候就更新掉了,就会判断不到两个节点值相同。

另一个是判断其根节点和左右孩子的值是否相同时,如果是用当前节点和其左右孩子去比他们的值是否相同,显然增加了代码量,且有悖于DFS的思想,极大增加了运行时间,会变成类似BFS搜索的样子,因此该题的正确思路应该是判断当前节点是否与其父节点的值相同。

       除此之外,本题没有使用一个二维数组进行值的存放和当前值的连续路径长度,是因为递归过程需要多次判断值是否相同,相同后再对路径长度进行修改,即需要多次对二维数组的某一行进行操作,如果使用二维数组会增加运行时间。因此本代码使用了两个一维数组进行存储,同时因为题目没有设置二叉树节点值的最大值,如果值非常的大,那么数组的长度也会非常的大,所以本项目使用了动态数组进行存储,注意不能使用哈希表、图、二元组等数据结构进行存储,因为这些数据结构的值是无法修改的。

代码和运行结果

#include <bits/stdc++.h>
using namespace std;

typedef struct BinTree
{
	int data;
	BinTree* pleft;
	BinTree* pright;
	BinTree* parent;
}T;

int ans,lens;
vector<int> no;
vector<int> l;


T* CreateTree()
{
	T* pa = (T*)malloc(sizeof(T));
	T* pb = (T*)malloc(sizeof(T));
	T* pc = (T*)malloc(sizeof(T));
	T* pd = (T*)malloc(sizeof(T));
	T* pe = (T*)malloc(sizeof(T));
	T* pf = (T*)malloc(sizeof(T));
	pa->data = 5;
	pa->pright = pc;
	pa->pleft = pb;
	pb->data = 4;
	pc->data = 5;
	pb->pleft = pd;
	pb->pright = pe;
	pc->pleft = NULL;
	pc->pright = pf;
	pd->data = 1;
	pe->data = 1;
	pf->data = 5;
	pd->pleft = NULL;
	pd->pright = NULL;
	pe->pleft = NULL;
	pe->pright = NULL;
	pf->pleft = NULL;
	pf->pright = NULL;
	pa->parent = NULL;
	pb->parent = pa;
	pc->parent = pa;
	pd->parent = pb;
	pe->parent = pb;
	pf->parent = pc;
	return pa;
}

void DFS(T* tree)
{
	if (tree== NULL)
		return;
	if (tree->parent == NULL || tree->parent->data != tree->data) //不连续
	{
		no.push_back(tree->data);
		l.push_back(1);
	}
	else//连续
	{
		int i;
		for (i = no.size()-1;i >= 0;i--)
		{
			if (no[i] == tree->data)
				break;
		}
		l[i]++;
	}
	DFS(tree->pleft);
	DFS(tree->pright);
	return;
}

int main()
{
	T* ptop = CreateTree();
	DFS(ptop);
	ans = no[0];
	lens = l[0];
	for (int i = 1;i < no.size();i++)
	{
		if (l[i] > lens)
		{
			lens = l[i];
			ans = no[i];
		}
	}
	cout << "最长路径的元素是" << ans <<endl;
	cout << "其长度是" << lens << endl;

	return 0;
}

DFS的本质就是递归,所以考虑的事情就四个:是否需要返回值,是否需要回溯,递归终止条件是什么,函数执行体。本题是为了寻找同值最长路径,所以函数执行体就是判断两个节点是否同值以及是否连续;因为是二叉树的DFS,所以终止条件就是遍历到叶子节点的时候就停止递归;因为此题没有对二叉树进行任何的修改,所以也不需要回溯;本题只需要对每个节点进行判断操作,也不需要利用节点信息进行其他算术运算,所以也不需要返回值。以此就能写出本题代码。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值