二叉树问题---移动石子

【座右铭】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部分:测试用例





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值