给定像
这样的节点class Node
{
public int Val { get; set; }
public Node Parent { get; set; }
public List<Node> Children { get; set; } = new List<Node>();
/// <summary>
/// Sum of values in descendant nodes
/// </summary>
public int DescendantsSum { get; set; } = 0;
/// <summary>
/// Sum of values in tree whose root is this node
/// </summary>
public int TreeSum { get { return Val + DescendantsSum; } }
}
以及Node
s已设置Val
s的树,我尝试做的是我写的以下方法摘要中描述的内容
/// <summary>
/// Given a tree like
///
/// Val=100
/// \
/// Val=200
/// / \
/// / Val=100
/// Val=100
/// / \
/// Val=500 Val=600
///
/// set a field for each node showing the sum of the values
/// in the subtree whose root is that node, making it into
///
/// Val=100
/// Sum=1600
/// \
/// Val=200
/// Sum=1500
/// / \
/// / Val=100
/// / Sum=100
/// Val=100
/// Sum=1200
/// / \
/// Val=500 Val=600
/// Sum=500 Sum=600
///
/// </summary>
static void SetSums(Node[] nodes)
{
foreach(var leaf in nodes.Where(node => node.Children.Count == 0))
for(var cur = leaf; cur.Parent != null; cur = cur.Parent)
cur.Parent.DescendantsSum += cur.TreeSum;
}
但是,这会导致错误的较大值,例如3400
,它应该是1600
。我已经考虑过我的算法,但我无法看到它存在缺陷。任何提示?
答案 0 :(得分:3)
当你使用树木时,它有时更容易从顶部移动到底部,而不是像你一样。“
我认为这应该可以满足您的需求:
public class Node
{
public int Val { get; set; }
public Node Parent { get; set; }
public List<Node> Children { get; set; } = new List<Node>();
/// <summary>
/// Sum of values in descendant nodes
/// </summary>
public int DescendantsSum
{
get
{
var sum = 0;
foreach(var child in Children)
{
sum += child.TreeSum;
//You can do this instead
//sum += child.Val;
//sum += child.DescendantsSum;
}
return sum;
}
}
/// <summary>
/// Sum of values in tree whose root is this node
/// </summary>
public int TreeSum { get { return Val + DescendantsSum; } }
}
或者使用LINQ:
public int DescendantsSum
{
get
{
return Children.Sum(child => child.TreeSum);
}
}
答案 1 :(得分:1)
我不打算讨论自上而下和自下而上的算法。你选择了自下而上的罚款,那么缺陷在哪里?
考虑以下简单树:
child1
\
parent - grandparent
/
child2
您的算法将执行:
parent.DescendantsSum += child1.TreeSum;
grandparent.DescendantsSum += parent.TreeSum;
parent.DescendantsSum += child2.TreeSum;
grandparent.DescendantsSum += parent.TreeSum;
正如您所看到的,parent.TreeSum
被添加两次grandparent.DescendantsSum
,导致错误的结果。
由于DescendantsSum
实际上是所有后代节点的Val
的总和,因此修复算法的一种方法是处理所有节点并将节点Val
添加到每个节点父节点
static void SetSums(Node[] nodes)
{
foreach (var node in nodes)
node.DescendantsSum = 0;
foreach (var node in nodes)
for (var parent = node.Parent; parent != null; parent = parent.Parent)
parent.DescendantsSum += node.Val;
}
答案 2 :(得分:0)
你需要一个递归函数 这很好用:
class NodeTest
{
public static void Run()
{
var root = new Node() { Val = 1 };
var a1 = new Node() { Val = 2 };
var a2 = new Node() { Val = 3 };
var a11 = new Node() { Val = 4 };
var a12 = new Node() { Val = 5 };
var a13 = new Node() { Val = 6 };
var a21 = new Node() { Val = 7 };
var a22 = new Node() { Val = 8 };
a1.Children.AddRange(new Node[] { a11, a12, a13 });
a2.Children.AddRange(new Node[] { a21, a22 });
root.Children.AddRange(new Node[] { a1, a2 });
Console.WriteLine(root.DescendantsSum);
Console.WriteLine(root.TreeSum);
Console.WriteLine();
Console.WriteLine(a1.DescendantsSum);
Console.WriteLine(a1.TreeSum);
}
}
class Node
{
public int Val { get; set; }
public List<Node> Children { get; set; }
/// <summary>
/// Sum of values in descendant nodes
/// </summary>
public int DescendantsSum
{
get
{
return TreeSum - Val;
}
}
/// <summary>
/// Sum of values in tree whose root is this node
/// </summary>
public int TreeSum
{
get
{
return GetTreeSum(this);
}
}
public Node()
{
Children = new List<Node>();
}
private int GetTreeSum(Node node)
{
int result = 0;
if (node.Children.Count > 0)
{
result += node.Val;
node.Children.ForEach(c => { result += GetTreeSum(c); });
}
else
result += node.Val;
return result;
}
}