计算两个节点之间的最长路径 路径在拱门中 签名的方法是:
public static int longestPath(Node n)
在下面的示例二叉树中,它是 4 (通过2-3-13-5-2)。
这就是我现在所拥有的,对于给定的树,它只返回0。
public static int longestPath(Node n) {
if (n != null) {
longestPath(n, 0);
}
return 0;
}
private static int longestPath(Node n, int prevNodePath) {
if (n != null && n.getLeftSon() != null && n.getRightSon() != null) {
int currNodePath = countLeftNodes(n.getLeftSon()) + countRightNodes(n.getRightSon());
int leftLongestPath = countLeftNodes(n.getLeftSon().getLeftSon()) + countRightNodes(n.getLeftSon().getRightSon());
int rightLongestPath = countLeftNodes(n.getRightSon().getLeftSon()) + countRightNodes(n.getRightSon().getRightSon());
int longestPath = currNodePath > leftLongestPath ? currNodePath : leftLongestPath;
longestPath = longestPath > rightLongestPath ? longestPath : rightLongestPath;
longestPath(n.getLeftSon(), longestPath);
longestPath(n.getRightSon(), longestPath);
return longestPath > prevNodePath ? longestPath : prevNodePath;
}
return 0;
}
private static int countLeftNodes(Node n) {
if (n != null) {
return 1+ countLeftNodes(n.getLeftSon());
}
return 0;
}
private static int countRightNodes(Node n) {
if (n != null) {
return 1+ countRightNodes(n.getRightSon());
}
return 0;
}
我明白我在某个地方错过了一个关键概念......当我尝试跟踪执行流程时,我的大脑发疯了...
我是否正确地说,通过找到根中最长的路径,它的左边和右边。右边的节点,然后在它的左边和后面递归。右边节点传递它们从前一个方法调用开始的最长路径,最后(当?)返回最长路径时,我不确定你如何返回它......
答案 0 :(得分:14)
也许就是这么简单:
public static int longestPath(Node n) {
if (n != null) {
return longestPath(n, 0); // forgot return?
}
return 0;
}
它比一见钟情更复杂。考虑以下树:
1
/ \
2 3
/ \
4 5
/ \ \
6 7 8
/ \ \
9 a b
在这种情况下,根节点甚至不在最长路径(a-7-4-2-5-8-b
)。
因此,您必须做的是以下内容:对于每个节点n
,您必须计算以下内容:
L
)R
)l
)r
)然后,决定哪种组合最大化路径长度:
L+R+2
,即从左子树中的子路径到当前节点,从当前节点到右子树中的子路径l
,即只取左侧子树并从路径中排除当前节点(从而右侧子树)r
,即只需选择正确的子树并从路径中排除当前节点(从而保留左子树)所以我会做一点点破解,并且每个节点都不会只返回一个int
,而是包含(L+R+2, l, r)
的三个整数。然后,呼叫者必须根据上述规则决定如何处理此结果。
答案 1 :(得分:12)
正确的算法是:
这个算法肯定会起作用,你也不仅限于二叉树。我不确定你的算法:
我说得对,通过找到根中最长的路径,它的左边和右边。右边的节点,然后在它的左边和后面递归。右边节点传递它们从前一个方法调用开始的最长路径,最后(当???)返回最长路径时,我不确定你如何返回它...
因为我不明白你究竟在描述什么。你可以手工制作一个例子或尝试更好地解释它吗?这样你就可以更好地帮助理解它是否正确。
您似乎正在尝试递归实现基本相同的事情,只是简化了二叉树。但是,对于这个问题,您的代码似乎相当复杂查看讨论here以获得更简单的实现。
答案 2 :(得分:2)
这是我在C ++中的递归解决方案:
int longest_dis(Node* root) {
int height1, height2;
if( root==NULL)
return 0;
if( root->left == NULL ) && ( root->right == NULL )
return 0;
height1 = height(root->left); // height(Node* node) returns the height of a tree rooted at node
height2 = height(root->right);
if( root->left != NULL ) && ( root->right == NULL )
return max(height1+1, longest_dis(root->left) );
if( root->left == NULL ) && ( root->right != NULL )
return max(height2+1, longest_dis(root->right) );
return max(height1+height2+2, longest_dis(root->left), longestdis(root->right) );
}
答案 3 :(得分:2)
public int longestPath() {
int[] result = longestPath(root);
return result[0] > result[1] ? result[0] : result[1];
}
// int[] {self-contained, root-to-leaf}
private int[] longestPath(BinaryTreeNode n) {
if (n == null) {
return new int[] { 0, 0 };
}
int[] left = longestPath(n.left);
int[] right = longestPath(n.right);
return new int[] { Util.max(left[0], right[0], left[1] + right[1] + 1),
Util.max(left[1], right[1]) + 1 };
}
答案 4 :(得分:2)
简单实施:
int maxDepth(Node root) {
if(root == null) {
return 0;
} else {
int ldepth = maxDepth(root.left);
int rdepth = maxDepth(root.right);
return ldepth>rdepth ? ldepth+1 : rdepth+1;
}
}
int longestPath(Node root)
{
if (root == null)
return 0;
int ldepth = maxDepth(root.left);
int rdepth = maxDepth(root.right);
int lLongPath = longestPath(root.left);
int rLongPath = longestPath(root.right);
return max(ldepth + rdepth + 1, max(lLongPath, rLongPath));
}
答案 5 :(得分:1)
我认为你过于复杂了。
考虑通过节点n的最长路径,而不是上升到n的父路径。该路径的长度与连接到n?
的两个子区的高度之间的关系是什么?在弄清楚之后,检查树递归推理如下:
具有根n的子树的最长路径是以下三个中的最长路径:
答案 6 :(得分:1)
如果,对于每个节点n
,您的目标是计算这两个数字:
n
):树中最长路径的长度,以n
n
):以n
为根的树的高度。对于每个终端节点(具有null
左右节点的节点),很明显f和h都是0。
现在,每个节点n
的h是:
n.left
和n.right
都是null
,则n.left
),如果只有n.left
为非null
n.right
),如果只有n.right
为非null
n.left
),h(n.right
))如果n.left
和n.right
都不是null
f(n
)是:
n.left
和n.right
都是null
,则n.left
),h(n
))如果只有n.left
为非null
n.right
不是null
n.left
和n.right
都不是 - null
(你需要弄清楚是什么取代了两个“??”占位符。有一些选择使这个策略有效。我已亲自测试过。)
然后,longestPath(Node n)
只是f(n
):
public class SO3124566
{
static class Node
{
Node left, right;
public Node()
{
this(null, null);
}
public Node(Node left, Node right)
{
this.left = left;
this.right = right;
}
}
static int h(Node n)
{
// ...
}
static int f(Node n)
{
// ...
}
public static int longestPath(Node n)
{
return f(n);
}
public static void main(String[] args)
{
{ // @phimuemue's example
Node n6 = new Node(),
n9 = new Node(),
a = new Node(),
n7 = new Node(n9, a),
n4 = new Node(n6, n7),
b = new Node(),
n8 = new Node(null, b),
n5 = new Node(null, n8),
n2 = new Node(n4, n5),
n3 = new Node(),
n1 = new Node(n2, n3);
assert(longestPath(n1) == 6);
}{ // @Daniel Trebbien's example: http://pastebin.org/360444
Node k = new Node(),
j = new Node(k, null),
g = new Node(),
h = new Node(),
f = new Node(g, h),
e = new Node(f, null),
d = new Node(e, null),
c = new Node(d, null),
i = new Node(),
b = new Node(c, i),
a = new Node(j, b);
assert(longestPath(a) == 8);
}
assert(false); // just to make sure that assertions are enabled.
// An `AssertionError` is expected on the previous line only.
}
}
你应该能够编写f和h的递归实现来使这段代码工作;但是,这种解决方案非常低效。其目的只是为了理解计算。
为了提高效率,您可以使用memoization或将其转换为使用堆栈的非递归计算。
答案 7 :(得分:1)
好吧,嗯,如果我正确理解你的问题,这是我的解决方案[但在C ++中(对不起)]:
int h(const Node<T> *root)
{
if (!root)
return 0;
else
return max(1+h(root->left), 1+h(root->right));
}
void longestPath(const Node<T> *root, int &max)
{
if (!root)
return;
int current = h(root->left) + h(root->right) + 1;
if (current > max) {
max = current;
}
longestPath(root->left, max);
longestPath(root->right, max);
}
int longest()
{
int max = 0;
longestPath(root, max);
return max;
}
答案 8 :(得分:1)
考虑到@phimuemue示例和@IVlad解决方案,我决定自己检查一下,所以这是我在python中实现的@IVlad解决方案:
def longestPath(graph,start, path=[]):
nodes = {}
path=path+[start]
for node in graph[start]:
if node not in path:
deepestNode,maxdepth,maxpath = longestPath(graph,node,path)
nodes[node] = (deepestNode,maxdepth,maxpath)
maxdepth = -1
deepestNode = start
maxpath = []
for k,v in nodes.iteritems():
if v[1] > maxdepth:
deepestNode = v[0]
maxdepth = v[1]
maxpath = v[2]
return deepestNode,maxdepth +1,maxpath+[start]
if __name__ == '__main__':
graph = { '1' : ['2','3'],
'2' : ['1','4','5'],
'3' : ['1'],
'4' : ['2','6','7'],
'5' : ['2','8'],
'6' : ['4'],
'7' : ['4','9','a'],
'8' : ['5','b'],
'9' : ['7'],
'a' : ['7'],
'b' : ['8']
}
"""
1
/ \
2 3
/ \
4 5
/ \ \
6 7 8
/ \ \
9 a b
"""
deepestNode,maxdepth,maxpath = longestPath(graph,'1')
print longestPath(graph, deepestNode)
>>> ('9', 6, ['9', '7', '4', '2', '5', '8', 'b'])