假设有一棵有 N 个节点的无向树, 编号为 1 到 N, 每一个节点都有一个int类型的值,不同的节点可以有相同的值。给一个长度为N的数组A,A[j]表示第j + 1个节点的值。再给一个长度为 (N - 1) * 2 的数组 E,对于任意的 0 <= j <= N - 2 都有 E[2 * j], E[2 * j + 1]表示节点 E[2 * j] 与节点 E[2 * j + 1]有边相连。返回具有相同值的节点构成的最长路劲的长度,路劲的长度为路径边的数量。
注意事项:
假设: 1 <= N <= 1000
样例:
给出 A = [1, 1, 1 ,2, 2] 和 E = [1, 2, 1, 3, 2, 4, 2, 5]
描述了下面的这棵树:
1 (value = 1)
/ \
(value = 1) 2 3 (value = 1)
/ \
(value = 2) 4 5 (value = 2)
你写的程序需要返回 2,因为最长路径为 2 -> 1 -> 3(所有节点的值均为1)。这条路径的边的数量为 2,所以答案是 2
思路:
刚开始想着由依赖关系构成树,找到根节点,由此转化为求树的最长相同值路径。
出错,才发现依赖关系只是相连无法找到根节点构成树。
#ifndef C717_H
#define C717_H
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
class Solution {
public:
/*
* @param : as indicated in the description
* @param : as indicated in the description
* @return: Return the number of edges on the longest path with same value.
*/
int LongestPathWithSameValue(vector<int> &A, vector<int> &E) {
// write your code here
if (A.size() == 1)
return 0;
vector<vector<int>> nums(A.size()+1);
vector<int> v(A.size(), 0);
for (int i = 0; i < E.size(); i = i + 2)
{
nums[E[i]].push_back(E[i + 1]);
v[E[i + 1]-1] = 1;
}
int root = 0;
for (int i = 0; i < A.size(); ++i)
{
if (v[i] == 0)
root = i + 1;
}
int num = 0;
CountPath(nums, A, root, num);
return num;
}
int CountPath(vector<vector<int>> nums, vector<int> A, int root, int &res)
{
if (nums[root].size() == 0)
return 0;
vector<int> tmp(nums[root].size(), 0);
for (int i = 0; i < nums[root].size(); ++i)
{
tmp[i] = CountPath(nums, A, nums[root][i], res);
}
for (int i = 0; i < nums[root].size(); ++i)
{
if (A[root - 1] == A[nums[root][i] - 1])
tmp[i] = tmp[i] + 1;
else
tmp[i] = 0;
}
sort(tmp.begin(), tmp.end());
if (nums[root].size() == 1)
res = maxVal(res, tmp[0]);
else
res = maxVal(res, tmp[nums[root].size() - 1] + tmp[nums[root].size() - 2]);
return tmp.back();
}
int maxVal(int a, int b)
{
return a > b ? a : b;
}
};
#endif
之后,利用深度搜索,先对相连接的节点构建双向映射,递归地计算出当前节点的最长相同值路径,
最后得到结果。
#ifndef C717_H
#define C717_H
#include<iostream>
#include<vector>
#include<map>
#include<algorithm>
using namespace std;
class Solution {
public:
/*
* @param : as indicated in the description
* @param : as indicated in the description
* @return: Return the number of edges on the longest path with same value.
*/
int LongestPathWithSameValue(vector<int> &A, vector<int> &E) {
// write your code here
if (A.size() == 1)
return 0;
vector<vector<int>> nums(A.size()+1);
for (int i = 0; i < E.size(); i = i + 2)//对于相连的节点建立双向映射
{
nums[E[i]].push_back(E[i + 1]);
nums[E[i + 1]].push_back(E[i]);
}
int res = 0;
CountPath(nums, A, 0, 1,res);
return res;
}
//递归,root表示已经处理过得节点,cur表示正在处理的节点,res表示最长向同值路径的长度
int CountPath(vector<vector<int>> nums, vector<int> A, int root, int cur,int &res)
{
vector<int> tmp;
for (auto c : nums[cur])
{
if (c != root)
{
//如果其子结点存在且和当前节点值相同,其长度加1
if (A[c - 1] == A[cur - 1])
tmp.push_back(CountPath(nums, A, cur, c,res)+1);
else
CountPath(nums, A, cur, c,res);
}
}
//为了防止tmp为空
tmp.push_back(0);
tmp.push_back(0);
sort(tmp.begin(), tmp.end());
//利用子节点中的最大的两个值来更新res
res = maxVal(res, tmp[tmp.size()-1] + tmp[tmp.size() - 2]);
return tmp.back();//如果路径还要加上父节点,则选择子节点中值最大的那个
}
int maxVal(int a, int b)
{
return a > b ? a : b;
}
};
#endif