题目出处:http://blog.youkuaiyun.com/v_JULY_v/article/details/6313257
题目:
假设有一颗二叉树,已知这棵树的节点上不均匀的分布了若干石头,石头数跟这棵二叉树的节点数相同,石头只可以在子节点和父节点之间进行搬运,每次只能搬运一颗石头。请问如何以最少的步骤将石头搬运均匀,使得每个节点上的石头上刚好为1。
我的思路:
1.程序所需数据结构:构造一棵和原二叉树骨骼相同的二叉树(不妨叫:仿造二叉树),仿造二叉树中每个节点只存储以下信息:
信息 #1:原二叉树中以相应节点为根的子二叉树的节点总数和所包含的石头总数的差值。
2.程序执行过程,三次遍历二叉树:
遍历#1:后序遍历两棵二叉树,在访问原每一个节点的时候分两种情况:
情况#1:如果该节点是叶子节点,则将该节点的石头个数减去1的结果保存到仿造二叉树的相应节点中。
情况#2:如果不是叶子节点,则将该节点的石头个数减去1,然后再加上其子女节点的数值的结果保存到仿造二叉树的相应节点中。
结果#1:仿造二叉树的每个节点中包含上述1中的信息#1.
结果#2:仿造二叉树的根节点中保存的结果值一定为0,因为原二叉树节点的个数与石头的个数相同。
遍历#2:后序遍历两棵二叉树,在访问仿造二叉树每个节点的时候分为两种情况:
情况#1:如果该节点的值小于等于0,则不做任何处理。
情况#2:如果该节点的值n大于0,且两个子女节点的值为n1,n2(叶节点的值为0),则如果n+n1+n2的值大于0,将n+n1+n2个石头从原节点的相应节点移动到其父节点。
结果#1:也是很重要的一个结果:每棵子树都已经达到了内部平衡,即节点个数等于石头个数。
遍历#3:先序遍历两棵二叉树,在遍历仿造二叉树的每个节点的时候,如果该节点的值n大于0,就将原二叉树中相应节点上的n个石头移动到值小于0的子女节点上。
优化:
1.将“信息#1”存入原二叉树中,并
且在每个节点中增加一个c,代表以该节点为根的子树的平衡度(石头总数减去节点总数)。
2.将“遍历#1”和“遍历#2”合并为一次后续遍历。
结果#1:每棵子树的根节点保存有该子树的平衡度c,而且c肯定小于或者等于0,而且整棵树的根节点的c肯定等于0.