【座右铭】1. 想要成为行家,就必须尝试解决大量的问题;
2. 解决大量问题并不代表能解决所有问题,而是表示解决下一个问题的几率变大了
1. 假设有1棵二叉树,已知这棵树的节点上不均匀地分布了若干石头,石头数跟这棵二叉树的节点数相同。石头只能在子节点和父节点之间搬迁,每次只能搬运一块石头。请问如何以最少的步骤将石头搬运均匀,使得每个节点上的石头刚好为1【问题来源于论坛】
第一部分:思路
从二叉树的最低层往上层走,对于最低层的节点只有1种选择:
1. 若石头数<1,则需从父节点上移动1个石头下来
2. 若石头数==1,则无需移动
3. 若石头数>1,则需要将额外的石头移动至父节点
举例说明:对于如下的二叉树
第二部分:Java代码,不考虑异常情况
class Node {
Node up; //父节点
Node left; //左子节点
Node right; //右子节点
int stone; //石头数
Node(int stone)
{
this.stone = stone;
}
}
public class Mover {
private Mover(){}
/**
* 假设有1棵二叉树,已知这棵树的节点上不均匀地分布了若干石头,石头数跟这棵二叉树的节点数相同。
* 石头只能在子节点和父节点之间搬迁,每次只能搬运一块石头。请问如何以最少的步骤将石头搬运均匀,
* 使得每个节点上的石头刚好为1
* @param root
* 根节点
* @param nodeNum
* 二叉树中节点数
* @return
* 最小的移动次数
*/
public static int move(Node root, int nodeNum)
{
//广度优先遍历树,并保存节点
Node[] set = new Node[nodeNum];
set[0] = root;
int k = 1;
for(int i=0;k<nodeNum;i++)
{
if(set[i].left!=null)
{
set[k++]=set[i].left;
}
if(set[i].right!=null)
{
set[k++]=set[i].right;
}
}
//从最低层往上走
k--;
int cost = 0;
while(k>=0)
{
Node current = set[k--];
if(current.up==null) //到了根节点
{
current.stone = 1;
break;
}else
{
int num = current.stone - 1;
if(num<0)
{
cost -= num;
}else if(num==0){}
else
{
cost += num;
}
current.up.stone += num;
current.stone = 1;
}
}
return cost;
}
}
第3部分:测试用例