题目
题目地址
[编程题]树上最长单色路径
对于一棵由黑白点组成的二叉树,我们需要找到其中最长的单色简单路径,其中简单路径的定义是从树上的某点开始沿树边走不重复的点到树上的另一点结束而形成的路径,而路径的长度就是经过的点的数量(包括起点和终点)。而这里我们所说的单色路径自然就是只经过一种颜色的点的路径。你需要找到这棵树上最长的单色路径。
给定一棵二叉树的根节点(树的点数小于等于300,请做到O(n)的复杂度),请返回最长单色路径的长度。这里的节点颜色由点上的权值表示,权值为1的是黑点,为0的是白点。
设计思想
经过每个节点的最长路径 = 经过左或右子节点的最长路径+到此节点之前的最长路径+1 或 =左右子节点的最长路径和+1 ,二者取其大者。
数学公式表示为:
maxPathRoot=max(max[maxPathLeft,maxPathRight]+1+maxPathbefore,maxPathLeft+maxPathRight+1)
还有一个限制条件,经过本节点的最大路径是要返回给父节点用的,如果本节点的值和父节点不相等,则应该返回0。
同样,到本节点前的最大路径,如果父节点和本节点值不相等,则本节点前最大路径为0,否则不修改。传递到子节点的时候+1。
遍历采用递归,递归函数的出口应该为节点为空,返回0。
最大值为全局变量,在递归的过程中修改。
函数设计如下:
经过本节点最长路径 = f(节点指针,父节点的值,到本节点之前的最大路径,全局最大值的引用)
{
1. 判断是否为空,若为空,返回0.
2. 判断本节点值和父节点是否相等,若不相等,到本节点前的最大路径为0,子节点递归完成后返回值为0.
3.开始递归,经过左节点最大路径=f(左节点指针,本节点值,到本节点前最大路径+1,全局最大值);
经过右节点最大路径=f(右节点指针,本节点值,到本节点前最大路径+1,全局最大值);
4. 经过本节点的最大路径=经过左节点最大路径+经过左节点最大路径+1 和 左右之中的最大路径+此前的最大路径+1 二者的大值。
5. 比较全局最大值,若大于全局最大值做出修改。
6. 准备返回,若和父节点不相等,返回0,若相等,返回左右子节点返回值的最大值+1.
}
代码
//经过根结点的单色路径长度,pval是父节点值 是之前到此点的最长路径
int maxPath(TreeNode* root,int pval,int lastpath,int & maxl){
if(root==NULL){
return 0;
}
if(root->val!=pval){
lastpath=0;
}
int lpath=maxPath(root->left,root->val,lastpath+1,maxl);
int rpath=maxPath(root->right,root->val,lastpath+1,maxl);
int mpath=max(lpath,rpath);
int mpath1=max(lpath+rpath+1,mpath+lastpath+1);
maxl=max(mpath1,maxl);
if(root->val!=pval){
return 0;
}
return mpath+1;
}
int findPath(TreeNode* root) {
// write code here
int maxl=0;
maxPath(root,-1,0,maxl);
return maxl;
}