minimum operation to make every leaf node equal
Last Updated :
28 Oct, 2023
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:
6
/ \
4 2
/ \ / \
1 9 5 3
/
10
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:
4
/ \
5 7
Output: 2
Explaination: 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 .2 is the minimum number of operations required to make leaf nodes at level 2 equal.
Approach: To solve the problem follow the below idea:
The idea is to 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.
Follow the steps to solve the problem:
- Start traversing the tree in level order and for every level check whether the current node is leaf or not if Yes then insert the current node’s value in a integer vector and once completing entire level pass the vector to another function which will calculate the minimum number of operation required ,for calculating the minimum number of operations do the below mentioned steps :
- Find the average of all elements present in leaf vector.
- Then traverse over the vector and find absolute difference between current element and average value and return this sum of absolute differences
- and then do the same for remaining value and add the total received by this function for multiple levels and return the sum .
Below code is implementation for above approach in C++:
C++
#include <bits/stdc++.h>
using namespace std;
struct node {
int data;
struct node* left;
struct node* right;
};
struct node* newNode( int data)
{
struct node* node
= ( struct node*) malloc ( sizeof ( struct node));
node->data = data;
node->left = NULL;
node->right = NULL;
return (node);
}
bool isLeaf(node* root)
{
if (root->left == NULL && root->right == NULL)
return true ;
return false ;
}
int findMinOperation(vector< int > leafs)
{
int val = leafs[0];
for ( int i = 1; i < leafs.size(); i++) {
val = (val + leafs[i]) / 2;
}
int ans
= 0;
for ( int i = 0; i < leafs.size(); i++) {
ans += abs (val - leafs[i]);
}
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;
for ( int i = 0; i < n; i++) {
node* temp = q.front();
q.pop();
if (temp->left != NULL)
q.push(temp->left);
if (temp->right != NULL)
q.push(temp->right);
if (isLeaf(temp))
leafs.push_back(temp->data);
}
if (leafs.size() > 1) {
minOperation += findMinOperation(leafs);
}
}
return minOperation;
}
int main()
{
struct node* root = newNode(6);
root->left = newNode(4);
root->right = newNode(2);
root->left->left = newNode(1);
root->left->right = newNode(9);
root->right->left = newNode(5);
root->right->right = newNode(3);
root->left->left->right = newNode(10);
cout << minimumOperation(root);
return 0;
}
|
Java
import java.util.LinkedList;
import java.util.Queue;
import java.util.Vector;
class Node {
int data;
Node left;
Node right;
Node( int data) {
this .data = data;
left = null ;
right = null ;
}
}
public class Main {
static boolean isLeaf(Node root) {
return root.left == null && root.right == null ;
}
static int findMinOperation(Vector<Integer> leafs) {
int val = leafs.get( 0 );
for ( int i = 1 ; i < leafs.size(); i++) {
val = (val + leafs.get(i)) / 2 ;
}
int ans = 0 ;
for ( int i = 0 ; i < leafs.size(); i++) {
ans += Math.abs(val - leafs.get(i));
}
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();
Vector<Integer> leafs = new Vector<>();
for ( int i = 0 ; i < n; i++) {
Node temp = q.poll();
if (temp.left != null )
q.add(temp.left);
if (temp.right != null )
q.add(temp.right);
if (isLeaf(temp))
leafs.add(temp.data);
}
if (leafs.size() > 1 ) {
minOperation += findMinOperation(leafs);
}
}
return minOperation;
}
public static void main(String[] args) {
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));
}
}
|
Python3
from queue import Queue
class Node:
def __init__( self , data):
self .data = data
self .left = None
self .right = None
def isLeaf(root):
if root.left is None and root.right is None :
return True
return False
def findMinOperation(leafs):
val = leafs[ 0 ]
for i in range ( 1 , len (leafs)):
val = (val + leafs[i]) / / 2
ans = 0
for i in range ( len (leafs)):
ans + = abs (val - leafs[i])
return ans
def minimumOperation(root):
if not root:
return 0
minOperation = 0
q = Queue()
q.put(root)
while not q.empty():
n = q.qsize()
leafs = []
for i in range (n):
temp = q.get()
if temp.left is not None :
q.put(temp.left)
if temp.right is not None :
q.put(temp.right)
if isLeaf(temp):
leafs.append(temp.data)
if len (leafs) > 1 :
minOperation + = findMinOperation(leafs)
return minOperation
if __name__ = = "__main__" :
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 (minimumOperation(root))
|
C#
using System;
using System.Collections.Generic;
public class Node
{
public int Data;
public Node Left;
public Node Right;
public Node( int data)
{
Data = data;
Left = null ;
Right = null ;
}
}
class Program
{
static bool IsLeaf(Node root)
{
return (root.Left == null && root.Right == null );
}
static int FindMinOperation(List< int > leafs)
{
int val = leafs[0];
for ( int i = 1; i < leafs.Count; i++)
{
val = (val + leafs[i]) / 2;
}
int ans = 0;
foreach ( int leaf in leafs)
{
ans += Math.Abs(val - leaf);
}
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 >();
for ( int i = 0; i < n; i++)
{
Node temp = q.Dequeue();
if (temp.Left != null )
q.Enqueue(temp.Left);
if (temp.Right != null )
q.Enqueue(temp.Right);
if (IsLeaf(temp))
leafs.Add(temp.Data);
}
if (leafs.Count > 1)
{
minOperation += FindMinOperation(leafs);
}
}
return minOperation;
}
static void Main()
{
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
class Node {
constructor(data) {
this .data = data;
this .left = null ;
this .right = null ;
}
}
function isLeaf(root) {
return !root.left && !root.right;
}
function findMinOperation(leafs) {
let val = leafs[0];
for (let i = 1; i < leafs.length; i++) {
val = (val + leafs[i]) / 2;
}
let ans = 0;
for (let i = 0; i < leafs.length; i++) {
ans += Math.abs(val - leafs[i]);
}
return ans;
}
function minimumOperation(root) {
if (!root) {
return 0;
}
let minOperation = 0;
const queue = [root];
while (queue.length > 0) {
const n = queue.length;
const leafs = [];
for (let i = 0; i < n; i++) {
const temp = queue.shift();
if (temp.left) {
queue.push(temp.left);
}
if (temp.right) {
queue.push(temp.right);
}
if (isLeaf(temp)) {
leafs.push(temp.data);
}
}
if (leafs.length > 1) {
minOperation += findMinOperation(leafs);
}
}
return minOperation;
}
const 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));
|
Time Complexity: O(N), traversing over the tree
Auxillary space: O(N), because of queue used
Share your thoughts in the comments
Please Login to comment...