Open In App

Minimum operation to make every leaf node equal

Last Updated : 22 Oct, 2024
Comments
Improve
Suggest changes
Like Article
Like
Report

Given a binary tree that contains multiple nodes, the task is to find a minimum number of operations required to make leaf nodes at the same level equal. By performing one operation you can either increase the node's value by one or decrease the node's value by one.

Examples:

Input:

minimum-operation-to-make-every-leaf-node-equal

Output: 6
Explanation: There is no leaf node at levels 1 and 2, we have 3 leaf nodes at level 3 which have values 9, 5, and 3. To make these three equal we can reduce 9 by 4 which will cost 4 operations then second leaf node 5 will remain the same and then the third leaf node will be incremented twice which will cost 2 operations. So in the end all leaf nodes at level three will have a value of 5 and this will cost a total of 6 operations. At level 4 there is only 1 leaf node so no operations will be performed here.

Input:

minimum-operation-to-make-every-leaf-node-equal-2

Output: 2
Explanation: There are two leaf nodes at level 2 which have values 5 and 7 so we can increment 5 by 2 and this will cost us 2 operations.

Approach:

The idea is to start traversing in level order manner and find the total number of nodes which we need to make equal in the same level then after finding these nodes calculate minimum number of operations by making each element equal to average of all elements.

Below code is implementation for above approach:

C++
// C++ implementation to calculate the minimum number of operations 
// required to make all leaf nodes of a binary tree equal
#include <bits/stdc++.h>
using namespace std;


class Node {
public:
    int data;
    Node* left;
    Node* right;
  	Node(int x){
    	data = x;
      	left = right = nullptr;
    }
};

// Function that returns true if current node
// is leaf otherwise false
bool isLeaf(Node* root) {
    if (root->left == NULL && root->right == NULL)
        return true;
    return false;
}

// Function that calculates minimum number
// of operations required to make all elements
// of array equal and return that value
int findMinOperation(vector<int>& leafs) {
    int val = leafs[0];

    // Running for loop for calculating the
    // average of all numbers present in array
    for (int i = 1; i < leafs.size(); i++) {
        val = (val + leafs[i]) / 2;
    }

    // So the number calculated as average is
    // the number which will be lead to
    // minimum operation
    int ans = 0;
    for (int i = 0; i < leafs.size(); i++) {
        ans += abs(val - leafs[i]);
    }

    // This ans will be the minimum number of
    // operations which will be required to
    // make every element equal
    return ans;
}

int minimumOperation(Node* root) {
    if (!root)
        return 0;

    int minOperation = 0;

    queue<Node*> q;
    q.push(root);

    while (!q.empty()) {
      
        int n = q.size();

        vector<int> leafs;

        // Traversing over the current level
        for (int i = 0; i < n; i++) {
            Node* curr = q.front();
            q.pop();
            if (curr->left != NULL)
                q.push(curr->left);
            if (curr->right != NULL)
                q.push(curr->right);

            // If current node is a leaf
            // node then push its value in
            // leafs vector
            if (isLeaf(curr))
                leafs.push_back(curr->data);
        }

        // If there are more than 1 leaf node in
        // current level than for making them
        // equal we will calculate minoperation
        if (leafs.size() > 1) {

            minOperation += findMinOperation(leafs);
        }
    }

    return minOperation;
}

int main() {
  
    // Initializing the tree
  	//           6
  	//          / \
    //         4   2
    //        / \ / \
    //       1  9 5  3
  	//      /
    //     10
  
    Node* root = new Node(6);
    root->left = new Node(4);
    root->right = new Node(2);
    root->left->left = new Node(1);
    root->left->right = new Node(9);
    root->right->left = new Node(5);
    root->right->right = new Node(3);
    root->left->left->right = new Node(10);

    cout << minimumOperation(root);

    return 0;
}
Java
// Java implementation to calculate the minimum number of operations 
// required to make all leaf nodes of a binary tree equal
import java.util.*;
class Node {
    int data;
    Node left, right;

    Node(int x) {
        data = x;
        left = right = null;
    }
}

class GfG {
  
    // Function that returns true if current node
  	// is leaf otherwise false
    static boolean isLeaf(Node root) {
        return (root.left == null && root.right == null);
    }

    // Function that calculates minimum number of operations required 
    // to make all elements of array equal and return that value
    static int findMinOperation(int[] leafs) {
        int val = leafs[0];

        // Running for loop for calculating the average 
      	// of all numbers present in array
        for (int i = 1; i < leafs.length; i++) {
            val = (val + leafs[i]) / 2;
        }

        // So the number calculated as average is the number
     	// which will lead to minimum operation
        int ans = 0; 
        for (int i = 0; i < leafs.length; i++) {
            ans += Math.abs(val - leafs[i]);
        }

        // This ans will be the minimum number of operations 
      	// which will be required to make every element equal
        return ans;
    }

    static int minimumOperation(Node root) {
        if (root == null)
            return 0;

        int minOperation = 0;

        Queue<Node> q = new LinkedList<>();
        q.add(root);

        while (!q.isEmpty()) {

            int n = q.size();
          
            List<Integer> leafs = new ArrayList<>();

            // Traversing over the current level
            for (int i = 0; i < n; i++) {
                Node curr = q.poll();
                if (curr.left != null)
                    q.add(curr.left);
                if (curr.right != null)
                    q.add(curr.right);

                // If current node is a leaf node then
              	// push its value in leafs vector
                if (isLeaf(curr))
                    leafs.add(curr.data);
            }

            // If there are more than 1 leaf node in
          	// current level than for making them equal
          	// we will calculate minoperation
            if (leafs.size() > 1) {
              
                int[] leafsArray = leafs.stream().mapToInt(i -> i).toArray();
                minOperation += findMinOperation(leafsArray);
            }
        }

        return minOperation;
    }

    public static void main(String[] args) {
      
        // Initializing the tree
        //           6
        //          / \
        //         4   2
        //        / \ / \
        //       1  9 5  3
        //      /
        //     10
      
        Node root = new Node(6);
        root.left = new Node(4);
        root.right = new Node(2);
        root.left.left = new Node(1);
        root.left.right = new Node(9);
        root.right.left = new Node(5);
        root.right.right = new Node(3);
        root.left.left.right = new Node(10);
        System.out.println(minimumOperation(root));
    }
}
Python
# Python implementation to calculate the minimum number of operations 
# required to make all leaf nodes of a binary tree equal

class Node:
    def __init__(self, x):
        self.data = x
        self.left = None
        self.right = None

def is_leaf(root):
    return root.left is None and root.right is None

def find_min_operation(leafs):
    val = leafs[0]

    # Running for loop for calculating the average
    # of all numbers present in array
    for i in range(1, len(leafs)):
        val = (val + leafs[i]) // 2

    # So the number calculated as average is the number
    # which will lead to minimum operation
    ans = sum(abs(val - leaf) for leaf in leafs)

    # This ans will be the minimum number of operations
    # which will be required to make every element equal
    return ans

def minimum_operation(root):
    if not root:
        return 0

    min_operation = 0

    q = [root]


    while q:
      
        n = len(q)
        leafs = []

        for _ in range(n):
            curr = q.pop(0)
            if curr.left:
                q.append(curr.left)
            if curr.right:
                q.append(curr.right)

            # If current node is a leaf node
            # then push its value in leafs vector
            if is_leaf(curr):
                leafs.append(curr.data)

        if len(leafs) > 1:
          
            min_operation += find_min_operation(leafs)
            
    return min_operation

# Initializing the tree
#           6
#          / \
#         4   2
#        / \ / \
#       1  9 5  3
#      /
#     10

root = Node(6)
root.left = Node(4)
root.right = Node(2)
root.left.left = Node(1)
root.left.right = Node(9)
root.right.left = Node(5)
root.right.right = Node(3)
root.left.left.right = Node(10)

print(minimum_operation(root))
C#
// C# implementation to calculate the minimum number of operations 
// required to make all leaf nodes of a binary tree equal

using System;
using System.Collections.Generic;

class Node {
    public int data;
    public Node left, right;

    public Node(int x) {
        data = x;
        left = right = null;
    }
}

class GfG {
  
    static bool IsLeaf(Node root) {
        return (root.left == null && root.right == null);
    }

    // Function that calculates minimum number of operations required 
    // to make all elements of array equal and return that value
    static int FindMinOperation(List<int> leafs) {
        int val = leafs[0];

        // Running for loop for calculating the average
      	// of all numbers present in array
        for (int i = 1; i < leafs.Count; i++) {
            val = (val + leafs[i]) / 2;
        }

        // So the number calculated as average is the number 
      	// which will lead to minimum operation
        int ans = 0; 
        for (int i = 0; i < leafs.Count; i++) {
            ans += Math.Abs(val - leafs[i]);
        }

        // This ans will be the minimum number of operations 
      	// which will be required to make every element equal
        return ans;
    }

    static int MinimumOperation(Node root) {
        if (root == null)
            return 0;

        int minOperation = 0;
        Queue<Node> q = new Queue<Node>();
        q.Enqueue(root);

        while (q.Count > 0) {
            int n = q.Count;
            List<int> leafs = new List<int>();

            // Traversing over the current level
            for (int i = 0; i < n; i++) {
                Node curr = q.Dequeue();
                if (curr.left != null)
                    q.Enqueue(curr.left);
                if (curr.right != null)
                    q.Enqueue(curr.right);

                // If current node is a leaf node then
              	// push its value in leafs vector
                if (IsLeaf(curr))
                    leafs.Add(curr.data);
            }
          
            if (leafs.Count > 1) {
                minOperation += FindMinOperation(leafs);
            }
        }
        return minOperation;
    }

    static void Main(string[] args) {
      
        // Initializing the tree
        //           6
        //          / \
        //         4   2
        //        / \ / \
        //       1  9 5  3
        //      /
        //     10

        Node root = new Node(6);
        root.left = new Node(4);
        root.right = new Node(2);
        root.left.left = new Node(1);
        root.left.right = new Node(9);
        root.right.left = new Node(5);
        root.right.right = new Node(3);
        root.left.left.right = new Node(10);

        Console.WriteLine(MinimumOperation(root));
    }
}
JavaScript
// JavaScript implementation to calculate the
// minimum number of operations required to make all 
// leaf nodes of a binary tree equal

class Node {
    constructor(x) {
        this.data = x;
        this.left = this.right = null;
    }
}

function isLeaf(root) {
    return root.left === null && root.right === null;
}

function findMinOperation(leafs) {
    let val = leafs[0];

    // Running for loop for calculating the average 
    // of all numbers present in array
    for (let i = 1; i < leafs.length; i++) {
        val = Math.floor((val + leafs[i]) / 2);
    }

    // So the number calculated as average is the number 
    // which will lead to minimum operation
    let ans = 0; 
    for (let i = 0; i < leafs.length; i++) {
        ans += Math.abs(val - leafs[i]);
    }

    // This ans will be the minimum number of operations 
    // which will be required to make every element equal
    return ans;
}

function minimumOperation(root) {
    if (!root) return 0;
    let minOperation = 0;
    
    let q = [root];

    while (q.length > 0) {
    
        let n = q.length;
        let leafs = [];

        for (let i = 0; i < n; i++) {
            let curr = q.shift();
            if (curr.left) q.push(curr.left);
            if (curr.right) q.push(curr.right);
            
            if (isLeaf(curr)) leafs.push(curr.data);
        }

        if (leafs.length > 1) {
            minOperation += findMinOperation(leafs);
        }
    }

    return minOperation;
}

// Initializing the tree
//           6
//          / \
//         4   2
//        / \ / \
//       1  9 5  3
//      /
//     10

let root = new Node(6);
root.left = new Node(4);
root.right = new Node(2);
root.left.left = new Node(1);
root.left.right = new Node(9);
root.right.left = new Node(5);
root.right.right = new Node(3);
root.left.left.right = new Node(10);

console.log(minimumOperation(root));

Output
6

Time Complexity: O(n), where n is the number of nodes in tree.
Auxillary space: O(n).


Next Article
Practice Tags :

Similar Reads