📜  在二叉树中分发糖果

📅  最后修改于: 2021-04-23 18:04:51             🧑  作者: Mango

给定具有N个节点的二叉树,其中每个节点的值代表该节点上存在的糖果的数量,总共有N个糖果。一举一动,一个人可以选择两个相邻的节点,然后将一个糖果从一个节点移动到另一个节点(移动可以是从父节点到子节点,也可以是从子节点到父节点)。
任务是找到所需的移动次数,以使每个节点恰好拥有一个糖果。
例子:

Input :      3
           /   \
          0     0 
Output : 2
Explanation: From the root of the tree, we move one 
candy to its left child, and one candy to
its right child.

Input :      0
           /   \
          3     0  
Output :3
Explanation : From the left child of the root, we move 
two candies to the root [taking two moves]. Then, we move 
one candy from the root of the tree to the right child.

递归解决方案:
想法是从叶到根遍历树并连续平衡所有节点。要平衡一个节点,该节点上的糖果数量必须为1。
可能有两种情况:

  1. 如果一个节点需要糖果,如果树的节点有0个糖果(比其需要的糖果多-1),那么我们应该将糖果从其父节点推到该节点上。
  2. 如果节点有多个糖果。如果它说有4个糖果(超过3个),那么我们应该将3个糖果从节点推到其父节点。

因此,从该叶到其父叶的移动总数为abs(num_candies – 1)
一旦一个节点达到平衡,我们在其余的计算中就不必再考虑该节点了。
下面是上述方法的实现:

C++
// C++ program to distribute candies
// in a Binary Tree
 
#include 
using namespace std;
 
// Binary Tree Node
struct Node {
    int key;
    struct Node *left, *right;
};
 
// Utility function to create a new node
Node* newNode(int key)
{
    Node* temp = new Node;
    temp->key = key;
    temp->left = temp->right = NULL;
    return (temp);
}
 
// Utility function to find the number of
// moves to distribute all of the candies
int distributeCandyUtil(Node* root, int& ans)
{
    // Base Case
    if (root == NULL)
        return 0;
 
    // Traverse left subtree
    int l = distributeCandyUtil(root->left, ans);
 
    // Traverse right subtree
    int r = distributeCandyUtil(root->right, ans);
 
    // Update number of moves
    ans += abs(l) + abs(r);
 
    // Return number of moves to balance
    // current node
    return root->key + l + r - 1;
}
 
// Function to find the number of moves to
// distribute all of the candies
int distributeCandy(Node* root)
{
    int ans = 0;
 
    distributeCandyUtil(root, ans);
 
    return ans;
}
 
// Driver program
int main()
{
    /*  3
       / \
      0   0
             
    Let us create Binary Tree
    shown in above example */
 
    Node* root = newNode(3);
    root->left = newNode(0);
    root->right = newNode(0);
 
    cout << distributeCandy(root);
 
    return 0;
}


Java
// Java program to distribute candies
// in a Binary Tree
class GfG {
 
    // Binary Tree Node
    static class Node {
        int key;
        Node left, right;
    }
    static int ans = 0;
 
    // Utility function to create a new node
    static Node newNode(int key)
    {
        Node temp = new Node();
        temp.key = key;
        temp.left = null;
        temp.right = null;
        return (temp);
    }
 
    // Utility function to find the number of
    // moves to distribute all of the candies
    static int distributeCandyUtil(Node root)
    {
        // Base Case
        if (root == null)
            return 0;
 
        // Traverse left subtree
        int l = distributeCandyUtil(root.left);
 
        // Traverse right subtree
        int r = distributeCandyUtil(root.right);
 
        // Update number of moves
        ans += Math.abs(l) + Math.abs(r);
 
        // Return number of moves to balance
        // current node
        return root.key + l + r - 1;
    }
 
    // Function to find the number of moves to
    // distribute all of the candies
    static int distributeCandy(Node root)
    {
        distributeCandyUtil(root);
        return ans;
    }
 
    // Driver program
    public static void main(String[] args)
    {
        /* 3
    / \
    0 0
             
    Let us create Binary Tree
    shown in above example */
 
        Node root = newNode(3);
        root.left = newNode(0);
        root.right = newNode(0);
 
        System.out.println(distributeCandy(root));
    }
}
 
// This code is contributed by Prerna Saini.


Python3
# Python3 program to distribute candies
# in a Binary Tree
  
# Binary Tree Node
class Node:
     
    def __init__(self, key):
         
        self.key = key
        self.left = None
        self.right = None
  
# Utility function to create a new node
def newNode(key):
 
    temp = Node(key)
    return temp
  
# Utility function to find the number of
# moves to distribute all of the candies
def distributeCandyUtil( root, ans):
 
    # Base Case
    if (root == None):
        return 0, ans;
  
    # Traverse left subtree
    l,ans = distributeCandyUtil(root.left, ans);
  
    # Traverse right subtree
    r,ans = distributeCandyUtil(root.right, ans);
  
    # Update number of moves
    ans += abs(l) + abs(r);
  
    # Return number of moves to balance
    # current node
    return root.key + l + r - 1, ans;
  
# Function to find the number of moves to
# distribute all of the candies
def distributeCandy(root):
 
    ans = 0;
  
    tmp, ans = distributeCandyUtil(root, ans);
  
    return ans;
  
# Driver program
if __name__=='__main__':
     
    '''  3
       / \
      0   0
              
    Let us create Binary Tree
    shown in above example '''
  
    root = newNode(3);
    root.left = newNode(0);
    root.right = newNode(0);
  
    print(distributeCandy(root))
  
# This code is contributed by pratham76


C#
// C# program to distribute candies
// in a Binary Tree
using System;
 
class GFG {
 
    // Binary Tree Node
    public class Node {
        public int key;
        public Node left, right;
    }
    static int ans = 0;
 
    // Utility function to create a new node
    static Node newNode(int key)
    {
        Node temp = new Node();
        temp.key = key;
        temp.left = null;
        temp.right = null;
        return (temp);
    }
 
    // Utility function to find the number of
    // moves to distribute all of the candies
    static int distributeCandyUtil(Node root)
    {
        // Base Case
        if (root == null)
            return 0;
 
        // Traverse left subtree
        int l = distributeCandyUtil(root.left);
 
        // Traverse right subtree
        int r = distributeCandyUtil(root.right);
 
        // Update number of moves
        ans += Math.Abs(l) + Math.Abs(r);
 
        // Return number of moves to balance
        // current node
        return root.key + l + r - 1;
    }
 
    // Function to find the number of moves to
    // distribute all of the candies
    static int distributeCandy(Node root)
    {
        distributeCandyUtil(root);
        return ans;
    }
 
    // Driver Code
    public static void Main(String[] args)
    {
        /* 3
    / \
    0 0
             
    Let us create Binary Tree
    shown in above example */
 
        Node root = newNode(3);
        root.left = newNode(0);
        root.right = newNode(0);
 
        Console.WriteLine(distributeCandy(root));
    }
}
 
// This code is contributed by 29AjayKumar


C++
// C++ program to distribute
// candies in a Binary Tree
 
#include 
using namespace std;
 
// Binary Tree Node
struct Node {
    int key;
    struct Node *left, *right;
};
 
// Utility function to create a new node
Node* newNode(int key)
{
    Node* temp = new Node;
    temp->key = key;
    temp->left = temp->right = NULL;
    return (temp);
}
 
int countinchild(Node* root)
{
    // as node exists.
    if (root == NULL)
        return 0;
 
    int numberofnodes = 0; // to count total nodes.
    int sum = 0; // to count total candies present.
 
    queue q;
    q.push(root);
 
    while (q.size() != 0) {
        Node* f = q.front();
        q.pop();
 
        numberofnodes++;
        sum += f->key;
 
        if (f->left)
            q.push(f->left);
        if (f->right)
            q.push(f->right);
    }
 
    // as either less than 0 or greater, it will be counted as
    // move as explained in the approach.
 
    return abs(numberofnodes - sum);
}
 
int distributeCandy(Node* root)
{
    // moves will count for total no. of moves.
    int moves = 0;
 
    // as 0 node and 0 value.
    if (root == NULL)
        return 0;
 
    // as leaf node don't have to pass any candies.
    if (!root->left && !root->right)
        return 0;
 
    // queue to iterate on tree .
    queue q;
    q.push(root);
 
    while (q.size() != 0) {
        Node* f = q.front();
        q.pop();
 
        // total pass from left child
        moves += countinchild(f->left);
        // total pass from right child
        moves += countinchild(f->right);
 
        if (f->left)
            q.push(f->left);
        if (f->right)
            q.push(f->right);
    }
 
    return moves;
}
 
// Driver program
int main()
{
    /*  1
       / \
      0   2
               
    Let us create Binary Tree 
    shown in above example */
 
    Node* root = newNode(1);
    root->left = newNode(0);
    root->right = newNode(2);
 
    cout << distributeCandy(root);
 
    return 0;
}


Python3
# Python3 program to distribute
# candies in a Binary Tree
  
# Binary Tree Node
class Node:
     
    def __init__(self, key):
         
        self.key = key
        self.left = None
        self.right = None
  
# Utility function to create a new node
def newNode(key):
    temp = Node(key)
    return temp  
  
def countinchild(root):
 
    # as node exists.
    if (root == None):
        return 0;
    numberofnodes = 0; # to count total nodes.
    sum = 0; # to count total candies present.
  
    q = []
    q.append(root);
  
    while (len(q) != 0):       
        f = q[0];
        q.pop(0);
  
        numberofnodes += 1
        sum += f.key;
  
        if (f.left):
            q.append(f.left);
        if (f.right):
            q.append(f.right);
  
    # as either less than 0 or greater, it will be counted as
    # move as explained in the approach.
    return abs(numberofnodes - sum);
 
def distributeCandy(root):
 
    # moves will count for total no. of moves.
    moves = 0;
  
    # as 0 node and 0 value.
    if (root == None):
        return 0;
  
    # as leaf node don't have to pass any candies.
    if (not root.left and not root.right):
        return 0;
  
    # queue to iterate on tree .
    q = []
    q.append(root);
  
    while (len(q) != 0):       
        f = q[0];
        q.pop(0);
  
        # total pass from left child
        moves += countinchild(f.left);
     
        # total pass from right child
        moves += countinchild(f.right);
  
        if (f.left):
            q.append(f.left);
        if (f.right):
            q.append(f.right);
  
    return moves;
 
# Driver program
if __name__=='__main__':
     
    '''
    /  1
       / \
      0   2
                
    Let us create Binary Tree 
    shown in above example '''
  
    root = newNode(1);
    root.left = newNode(0);
    root.right = newNode(2);
    print(distributeCandy(root))
  
# This code is contributed by rutvik_56


输出

2

迭代解决方案:

方法:在每个节点上,一些糖果会从左边到右边,或者从右边到左边。在每种情况下,移动都会增加。因此,对于每个节点,我们将计算右侧孩子和左侧孩子中所需糖果的数量,每个孩子的节点总数(糖果总数) 。可能小于0,但在这种情况下也将被视为移动,因为额外的糖果也必须穿过根节点。

下面是迭代方法的实现:

C++

// C++ program to distribute
// candies in a Binary Tree
 
#include 
using namespace std;
 
// Binary Tree Node
struct Node {
    int key;
    struct Node *left, *right;
};
 
// Utility function to create a new node
Node* newNode(int key)
{
    Node* temp = new Node;
    temp->key = key;
    temp->left = temp->right = NULL;
    return (temp);
}
 
int countinchild(Node* root)
{
    // as node exists.
    if (root == NULL)
        return 0;
 
    int numberofnodes = 0; // to count total nodes.
    int sum = 0; // to count total candies present.
 
    queue q;
    q.push(root);
 
    while (q.size() != 0) {
        Node* f = q.front();
        q.pop();
 
        numberofnodes++;
        sum += f->key;
 
        if (f->left)
            q.push(f->left);
        if (f->right)
            q.push(f->right);
    }
 
    // as either less than 0 or greater, it will be counted as
    // move as explained in the approach.
 
    return abs(numberofnodes - sum);
}
 
int distributeCandy(Node* root)
{
    // moves will count for total no. of moves.
    int moves = 0;
 
    // as 0 node and 0 value.
    if (root == NULL)
        return 0;
 
    // as leaf node don't have to pass any candies.
    if (!root->left && !root->right)
        return 0;
 
    // queue to iterate on tree .
    queue q;
    q.push(root);
 
    while (q.size() != 0) {
        Node* f = q.front();
        q.pop();
 
        // total pass from left child
        moves += countinchild(f->left);
        // total pass from right child
        moves += countinchild(f->right);
 
        if (f->left)
            q.push(f->left);
        if (f->right)
            q.push(f->right);
    }
 
    return moves;
}
 
// Driver program
int main()
{
    /*  1
       / \
      0   2
               
    Let us create Binary Tree 
    shown in above example */
 
    Node* root = newNode(1);
    root->left = newNode(0);
    root->right = newNode(2);
 
    cout << distributeCandy(root);
 
    return 0;
}

Python3

# Python3 program to distribute
# candies in a Binary Tree
  
# Binary Tree Node
class Node:
     
    def __init__(self, key):
         
        self.key = key
        self.left = None
        self.right = None
  
# Utility function to create a new node
def newNode(key):
    temp = Node(key)
    return temp  
  
def countinchild(root):
 
    # as node exists.
    if (root == None):
        return 0;
    numberofnodes = 0; # to count total nodes.
    sum = 0; # to count total candies present.
  
    q = []
    q.append(root);
  
    while (len(q) != 0):       
        f = q[0];
        q.pop(0);
  
        numberofnodes += 1
        sum += f.key;
  
        if (f.left):
            q.append(f.left);
        if (f.right):
            q.append(f.right);
  
    # as either less than 0 or greater, it will be counted as
    # move as explained in the approach.
    return abs(numberofnodes - sum);
 
def distributeCandy(root):
 
    # moves will count for total no. of moves.
    moves = 0;
  
    # as 0 node and 0 value.
    if (root == None):
        return 0;
  
    # as leaf node don't have to pass any candies.
    if (not root.left and not root.right):
        return 0;
  
    # queue to iterate on tree .
    q = []
    q.append(root);
  
    while (len(q) != 0):       
        f = q[0];
        q.pop(0);
  
        # total pass from left child
        moves += countinchild(f.left);
     
        # total pass from right child
        moves += countinchild(f.right);
  
        if (f.left):
            q.append(f.left);
        if (f.right):
            q.append(f.right);
  
    return moves;
 
# Driver program
if __name__=='__main__':
     
    '''
    /  1
       / \
      0   2
                
    Let us create Binary Tree 
    shown in above example '''
  
    root = newNode(1);
    root.left = newNode(0);
    root.right = newNode(2);
    print(distributeCandy(root))
  
# This code is contributed by rutvik_56

输出
2