
Problem Statement
In this problem, you are given a binary tree where each node contains a certain number of coins. The tree has n
nodes, and the sum of all coins in the nodes equals n
. Your task is to redistribute the coins so that each node contains exactly one coin. The redistribution can occur through a series of moves, where one move involves transferring one coin between two adjacent nodes (viz., from a parent to its child or from a child to its parent).
You are required to determine and return the minimum number of moves necessary to achieve equal distribution of one coin per node across the entire tree.
Examples
Example 1
Input:
root = [3,0,0]
Output:
2
Explanation:
From the root of the tree, we move one coin to its left child, and one coin to its right child.
Example 2
Input:
root = [0,3,0]
Output:
3
Explanation:
From the left child of the root, we move two coins to the root [taking two moves]. Then, we move one coin from the root of the tree to the right child.
Constraints
- The number of nodes in the tree is
n
. 1 <= n <= 100
0 <= Node.val <= n
- The sum of all
Node.val
isn
.
Approach and Intuition
Given the constraints and the problem setup, here is the intuition and approach to solving this problem:
- Essentially, the move operation is a method of balancing the excess or deficiency of coins between adjacent nodes.
- A key observation is the concept of "net balance" of a node:
- If a node has more than one coin, it has an excess of coins, which it needs to pass to its neighbors.
- If a node has zero coins, it has a deficit and needs to receive coins from its neighbors.
- The approach involves a recursive traversal (e.g., DFS) of the tree:
- For each node, calculate how many coins it needs or has in excess after satisfying its own requirement of one coin.
- A positive balance indicates excess coins that need to be passed up to the parent or to the children.
- A negative balance indicates a deficit, so this node requires coins from its parent or can accept excess coins from its children.
- The recursion will calculate and return the number of moves required for each node based on its balance:
- When visiting a node, recursively determine the number of moves required for its left and right children.
- Adjust the coin distribution based on the balances returned by the children.
- The total number of moves for the current node is the sum of the moves required by its children plus any moves needed to transfer excess coins to or from this node.
- Start the recursive calculation from the root to cover the entire tree.
- Each transfer of a coin from a node to its adjacent node counts as one move.
The recursive process ensures that each node, after accounting for transfers, has exactly one coin, achieving the goal in the minimum number of moves by optimizing local balances progressively through the tree structure.
Solutions
- C++
- Java
- Python
class Solution {
public:
int coinDistribution(TreeNode* rootNode) {
totalMoves = 0;
explore(rootNode);
return totalMoves;
}
private:
int totalMoves; // Store the total number of moves
int explore(TreeNode* node) {
if (node == nullptr) return 0;
int leftExcess = explore(node->left); // excess coins in left child
int rightExcess = explore(node->right); // excess coins in right child
totalMoves += abs(leftExcess) + abs(rightExcess); // accumulate the moves needed
return (node->val - 1) + leftExcess + rightExcess; // calculate current node excess
}
};
The provided solution is a C++ class designed to determine the number of moves needed to distribute coins in a binary tree such that each node has exactly one coin. Here's a quick breakdown of how this solution operates:
The class
Solution
has a private integer membertotalMoves
which keeps track of the total number of coin redistribution moves required.The
coinDistribution
function is the public interface of the class, taking a pointer to the tree's root node as its argument. The function first setstotalMoves
to zero, then calls theexplore
function starting from the root node and returns the value oftotalMoves
.The private member function
explore
works recursively to calculate the excess or deficit of coins at each node in the tree:If the current node is
nullptr
, it returns 0, indicating no excess or deficiency.It recursively calculates the excess coins for both the left and right children of the current node.
The
totalMoves
is incremented by the sum of the absolute values of the left and right excesses. This increment represents the number of moves needed to balance the left and right children with the current node.Finally, it returns the excess coins at the current node, calculated as
(node->val - 1)
plus the left and right excess values. The-1
accounts for the coin that is to remain with the current node.
This solution efficiently calculates the minimum moves required by balancing coins from the bottom of the tree upwards, ensuring each node ends with exactly one coin after all redistributions.
class Solution {
private int totalMoves;
public int distributeCoins(TreeNode node) {
totalMoves = 0;
traverse(node);
return totalMoves;
}
private int traverse(TreeNode node) {
if (node == null) return 0;
int leftExcess = traverse(node.left);
int rightExcess = traverse(node.right);
totalMoves += Math.abs(leftExcess) + Math.abs(rightExcess);
return node.val - 1 + leftExcess + rightExcess;
}
}
The problem set involves redistributing coins such that every node of a binary tree has exactly one coin using the minimum number of moves. In this Java solution, a recursion-based approach is used to achieve the objective.
- Start with defining a private variable
totalMoves
to keep track of the number of moves made during redistribution. - Create a public function
distributeCoins
that initializestotalMoves
to zero and starts the recursion by calling thetraverse
function on the tree's root. This function returns thetotalMoves
counter when completed. - Implement a private helper function
traverse
that uses recursion to navigate through the tree. If the node is null, it returns zero, representing no excess coins to move. - For each node, calculate the excess coins in the left and right child through recursive calls to
traverse
. - Adjust
totalMoves
by adding the absolute value of the excess coins from both left and right children. This sum represents the minimum moves needed to make the current node balanced. - Return the excess from the current node which is the node value minus one (to make it balanced) added to the excess coins of left and right children combined. This value represents the net excess (positive or negative) that will be returned to the node's parent.
The essence of the solution lies in the recursive traversal and adjustment of the coin balance from the bottom of the tree to the top, ensuring minimum moves by only handling excess coins at each node.
class Solution:
def coinDistribution(self, root: Optional[TreeNode]) -> int:
self.total_moves = 0
def traverse(node):
if node == None:
return 0
# Compute the balance of coins in left and right children nodes
coins_left = traverse(node.left)
coins_right = traverse(node.right)
# Update total moves by adding the movements needed for balance
self.total_moves += abs(coins_left) + abs(coins_right)
# Calculate the number of spare coins current node has to give or needs
return (node.val - 1) + coins_left + coins_right
traverse(root)
return self.total_moves
The problem Distribute Coins in Binary Tree involves adjusting the number of coins on each node of a binary tree so that every node has exactly one coin. The challenge tasks you with calculating the minimum number of movements required to achieve this balance.
The provided Python solution involves a class Solution
with a method coinDistribution
that takes root
, a TreeNode
representing the root of the binary tree. The approach focuses on a depth-first search traversal of the tree to redistribute and count the movements of coins as follows:
Initialize a variable
self.total_moves
to count the required movements to balance the coins.Define and use a helper function,
traverse
, which:- Returns
0
if the node isNone
(base case for recursion) - Recursively calculates the required movements of coins in both left and right child nodes of the current node.
- Uses the absolute value of coins required or surplus in the left and right child nodes to update
self.total_moves
. - Determines the net coin balance for the current node and returns it, indicating how many coins need to be moved in or out.
- Returns
Call the helper function
traverse
starting from theroot
.Finally, return
self.total_moves
which now contains the minimum number of moves required to distribute the coins properly across the tree nodes.
This solution efficiently computes the result by traversing each node exactly once, making it performant with a complexity closely tied to the number of nodes in the tree.
No comments yet.