Minimum operations required to make every node at same level equal
Last Updated :
12 Nov, 2023
Given a binary tree, the task is to find the minimum number of operations required to make all nodes at the same level have the same value. You can achieve this by performing operations on the nodes, where each operation involves incrementing or decrementing a node’s value by one. Each operation has a cost of 1.
Examples:
Input:
61
/ \
7 2
/ \ / \
6 11 1 3
Output: 18
Explanation:
- Level 1 only contains one node so no operations here.
- Level 2 contains two nodes so either 7 can be decremented to 2 or 2 can be incremented to 7, both will cost 5 operations.
- Level 3 contains 4 nodes so all these nodes can be converted to 3 so it will cost a total of 13 operations.
- So total number of operations will be 5 + 13 = 18 operations.
Input:
1
/ \
13 7
/ / \
6 11 4
Output: 13
Explaination:
- No operations required for level 1.
- Minimum 6 operations required for level 2 as we can either increment 7 by 6 times or reduce 13 by 6 times.
- Total 7 operations required for level 3 as we can convert all nodes to 6 which will cost total 7 operations.
- So minimum operations required will be 6 + 7 = 13.
Approach: To solve the problem follow the below idea:
For solving this problem, we need to do level order traversal and store the entire level in a vector and if the number of nodes at current level is greater than 1 then calculate the minimum number of operations for making them equal.
Following steps are required for solving this problem :
- Start traversing the tree in level order and store the values of current node in a integer vector.
- If the current level contains more than 1 node then pass the vector after adding all the node’s values to findMin function which will return the minimum number of operations required to make the current level equal.
- Repeat the same for all the levels and add the number of operations for every level in another variable and return it.
- In findMin function, calculate the median of all elements present in the vector and then traverse over the vector and calculate the absolute difference between current element and median value. At last return the sum of all these differences.
Below Code is the implementation of 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);
}
int minOperation(vector< int > arr)
{
sort(arr.begin(), arr.end());
int median = arr[arr.size() / 2];
int ans = 0;
for ( int i = 0; i < arr.size(); i++) {
ans += abs (median - arr[i]);
}
return ans;
}
int findMinOp(node* root)
{
if (!root)
return 0;
int totalOperation = 0;
queue<node*> q;
q.push(root);
while (!q.empty()) {
int n = q.size();
vector< int > nodes;
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);
nodes.push_back(temp->data);
}
if (nodes.size() > 1) {
totalOperation += minOperation(nodes);
}
}
return totalOperation;
}
int main()
{
struct node* root = newNode(61);
root->left = newNode(7);
root->right = newNode(2);
root->left->left = newNode(1);
root->right->left = newNode(11);
root->right->right = newNode(6);
root->left->right = newNode(3);
cout << findMinOp(root);
return 0;
}
|
Java
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
class Node {
int data;
Node left, right;
Node( int data) {
this .data = data;
left = right = null ;
}
}
public class Main {
static int minOperation(ArrayList<Integer> arr) {
Collections.sort(arr);
int median = arr.get(arr.size() / 2 );
int ans = 0 ;
for ( int i = 0 ; i < arr.size(); i++) {
ans += Math.abs(median - arr.get(i));
}
return ans;
}
static int findMinOp(Node root) {
if (root == null )
return 0 ;
int totalOperation = 0 ;
Queue<Node> q = new LinkedList<>();
q.add(root);
while (!q.isEmpty()) {
int n = q.size();
ArrayList<Integer> nodes = new ArrayList<>();
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);
nodes.add(temp.data);
}
if (nodes.size() > 1 ) {
totalOperation += minOperation(nodes);
}
}
return totalOperation;
}
public static void main(String[] args) {
Node root = new Node( 61 );
root.left = new Node( 7 );
root.right = new Node( 2 );
root.left.left = new Node( 1 );
root.right.left = new Node( 11 );
root.right.right = new Node( 6 );
root.left.right = new Node( 3 );
System.out.println(findMinOp(root));
}
}
|
Python3
class Node:
def __init__( self , data):
self .data = data
self .left = None
self .right = None
def minOperation(arr):
arr.sort()
median = arr[ len (arr) / / 2 ]
total_operation = 0
for element in arr:
total_operation + = abs (median - element)
return total_operation
def findMinOp(root):
if not root:
return 0
total_operation = 0
queue = [root]
while queue:
n = len (queue)
nodes = []
for i in range (n):
node = queue.pop( 0 )
nodes.append(node.data)
if node.left:
queue.append(node.left)
if node.right:
queue.append(node.right)
if len (nodes) > 1 :
total_operation + = minOperation(nodes)
return total_operation
if __name__ = = "__main__" :
root = Node( 61 )
root.left = Node( 7 )
root.right = Node( 2 )
root.left.left = Node( 1 )
root.right.left = Node( 11 )
root.right.right = Node( 6 )
root.left.right = Node( 3 )
print (findMinOp(root))
|
C#
using System;
using System.Collections.Generic;
using System.Linq;
class Node
{
public int data;
public Node left, right;
public Node( int data)
{
this .data = data;
left = right = null ;
}
}
public class GFG
{
static int MinOperation(List< int > arr)
{
arr.Sort();
int median = arr[arr.Count / 2];
int ans = 0;
foreach ( int num in arr)
{
ans += Math.Abs(median - num);
}
return ans;
}
static int FindMinOp(Node root)
{
if (root == null )
return 0;
int totalOperation = 0;
Queue<Node> q = new Queue<Node>();
q.Enqueue(root);
while (q.Count > 0)
{
int n = q.Count;
List< int > nodes = 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);
nodes.Add(temp.data);
}
if (nodes.Count > 1)
{
totalOperation += MinOperation(nodes);
}
}
return totalOperation;
}
public static void Main( string [] args)
{
Node root = new Node(61);
root.left = new Node(7);
root.right = new Node(2);
root.left.left = new Node(1);
root.right.left = new Node(11);
root.right.right = new Node(6);
root.left.right = new Node(3);
Console.WriteLine(FindMinOp(root));
}
}
|
Javascript
class TreeNode {
constructor(data) {
this .data = data;
this .left = null ;
this .right = null ;
}
}
function minOperation(arr) {
arr.sort((a, b) => a - b);
const median = arr[Math.floor(arr.length / 2)];
let ans = 0;
for (let i = 0; i < arr.length; i++) {
ans += Math.abs(median - arr[i]);
}
return ans;
}
function findMinOp(root) {
if (!root) {
return 0;
}
let totalOperation = 0;
const queue = [];
queue.push(root);
while (queue.length > 0) {
const n = queue.length;
const nodes = [];
for (let i = 0; i < n; i++) {
const temp = queue.shift();
if (temp.left !== null ) {
queue.push(temp.left);
}
if (temp.right !== null ) {
queue.push(temp.right);
}
nodes.push(temp.data);
}
if (nodes.length > 1) {
totalOperation += minOperation(nodes);
}
}
return totalOperation;
}
const root = new TreeNode(61);
root.left = new TreeNode(7);
root.right = new TreeNode(2);
root.left.left = new TreeNode(1);
root.right.left = new TreeNode(11);
root.right.right = new TreeNode(6);
root.left.right = new TreeNode(3);
console.log(findMinOp(root));
|
Time Complexity: O(N*LogN)
Auxiliary Space: O(N)
Share your thoughts in the comments
Please Login to comment...