灵神真的强,这道题不知道如何遍历,没有什么其他思路,灵神给的边的计数器和移动次数联系在一起实在太妙了
题目
给你一个有 n
个结点的二叉树的根结点 root
,其中树中每个结点 node
都对应有 node.val
枚硬币。整棵树上一共有 n
枚硬币。
在一次移动中,我们可以选择两个相邻的结点,然后将一枚硬币从其中一个结点移动到另一个结点。移动可以是从父结点到子结点,或者从子结点移动到父结点。
返回使每个结点上 只有 一枚硬币所需的 最少 移动次数。
示例 1:
ini
输入: root = [3,0,0]
输出: 2
解释: 一枚硬币从根结点移动到左子结点,一枚硬币从根结点移动到右子结点。
代码与解析
使用了深度优先搜索来计算每个节点的多余硬币数目,对于每个节点,计算其左右子树的多余硬币数目,然后再加上当前节点的硬币数目减1(即缺少的硬币数)。累加每个节点移动的次数,并返回最小移动次数。
java
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
int ans = 0; // 记录移动次数
/**
* 计算移动硬币的最小次数
*
* @param root 树的根节点
* @return 返回最小移动次数
*/
public int distributeCoins(TreeNode root) {
dfs(root); // 调用深度优先搜索函数
return ans; // 返回最小移动次数
}
/**
* 深度优先搜索计算节点移动情况
*
* @param node 当前节点
* @return 返回节点的多余硬币数目
*/
public int dfs(TreeNode node) {
if (node == null) return 0; // 如果节点为空,返回0
// 计算左右子树的多余硬币数目,加上当前节点的硬币数目减1(即缺少的硬币数)
int d = dfs(node.left) + dfs(node.right) + node.val - 1;
ans += Math.abs(d); // 更新移动次数,累加当前节点的移动次数
return d; // 返回当前节点的多余硬币数目
}
}