Given an array which contains integer values, we need to make all values of this array equal to some integer value with minimum cost where the cost of changing an array value x to y is abs(x-y).
Examples :
Input : arr[] = [1, 100, 101]
Output : 100
We can change all its values to 100 with minimum cost,
|1 - 100| + |100 - 100| + |101 - 100| = 100
Input : arr[] = [4, 6]
Output : 2
We can change all its values to 5 with minimum cost,
|4 - 5| + |5 - 6| = 2
This problem can be solved by observing the cost while changing the target equal value, i.e. we will see the change in cost when target equal value is changed. It can be observed that, as we increase the target equal value the total cost decreases up to a limit and then starts increasing i.e. the cost graph with respect to target equal value is of U-shape and as cost graph is in U-shape, the ternary search can be applied to this search space and our goal is to get that bottom most point of the curve which will represent the smallest cost. We will make smallest and largest value of the array as the limit of our search space and then we will keep skipping 1/3 part of the search space until we reach to the bottom most point of our U-curve.
Please see below code for better understanding.
C++
#include <bits/stdc++.h>
using namespace std;
int computeCost( int arr[], int N, int X)
{
int cost = 0;
for ( int i = 0; i < N; i++)
cost += abs (arr[i] - X);
return cost;
}
int minCostToMakeElementEqual( int arr[], int N)
{
int low, high;
low = high = arr[0];
for ( int i = 0; i < N; i++) {
if (low > arr[i])
low = arr[i];
if (high < arr[i])
high = arr[i];
}
while ((high - low) > 2) {
int mid1 = low + (high - low) / 3;
int mid2 = high - (high - low) / 3;
int cost1 = computeCost(arr, N, mid1);
int cost2 = computeCost(arr, N, mid2);
if (cost1 < cost2)
high = mid2;
else
low = mid1;
}
return computeCost(arr, N, (low + high) / 2);
}
int main()
{
int arr[] = { 1, 100, 101 };
int N = sizeof (arr) / sizeof ( int );
cout << minCostToMakeElementEqual(arr, N);
return 0;
}
|
Java
import java.io.*;
public class GFG {
public static int computeCost( int arr[], int N,
int X)
{
int cost = 0 ;
for ( int i = 0 ; i < N; i++)
cost += Math.abs(arr[i] - X);
return cost;
}
public static int minCostToMakeElementEqual( int arr[],
int N)
{
int low, high;
low = high = arr[ 0 ];
for ( int i = 0 ; i < N; i++) {
if (low > arr[i])
low = arr[i];
if (high < arr[i])
high = arr[i];
}
while ((high - low) > 2 ) {
int mid1 = low + (high - low) / 3 ;
int mid2 = high - (high - low) / 3 ;
int cost1 = computeCost(arr, N, mid1);
int cost2 = computeCost(arr, N, mid2);
if (cost1 < cost2)
high = mid2;
else
low = mid1;
}
return computeCost(arr, N, (low + high) / 2 );
}
public static void main(String[] args)
{
int arr[] = { 1 , 100 , 101 };
int N = arr.length;
System.out.println(minCostToMakeElementEqual(arr, N));
}
}
|
Python3
def computeCost(arr, N, X):
cost = 0
for i in range (N):
cost + = abs (arr[i] - X)
return cost
def minCostToMakeElementEqual(arr, N):
low = high = arr[ 0 ]
for i in range (N):
if (low > arr[i]): low = arr[i]
if (high < arr[i]): high = arr[i]
while ((high - low) > 2 ):
mid1 = low + (high - low) / / 3
mid2 = high - (high - low) / / 3
cost1 = computeCost(arr, N, mid1)
cost2 = computeCost(arr, N, mid2)
if (cost1 < cost2):
high = mid2
else :
low = mid1
return computeCost(arr, N, (low + high) / / 2 )
arr = [ 1 , 100 , 101 ]
N = len (arr)
print (minCostToMakeElementEqual(arr, N))
|
C#
using System;
class GFG {
public static int computeCost( int [] arr, int N,
int X)
{
int cost = 0;
for ( int i = 0; i < N; i++)
cost += Math.Abs(arr[i] - X);
return cost;
}
public static int minCostToMakeElementEqual( int [] arr,
int N)
{
int low, high;
low = high = arr[0];
for ( int i = 0; i < N; i++) {
if (low > arr[i])
low = arr[i];
if (high < arr[i])
high = arr[i];
}
while ((high - low) > 2) {
int mid1 = low + (high - low) / 3;
int mid2 = high - (high - low) / 3;
int cost1 = computeCost(arr, N, mid1);
int cost2 = computeCost(arr, N, mid2);
if (cost1 < cost2)
high = mid2;
else
low = mid1;
}
return computeCost(arr, N, (low + high) / 2);
}
public static void Main()
{
int [] arr = { 1, 100, 101 };
int N = arr.Length;
Console.Write(minCostToMakeElementEqual(arr, N));
}
}
|
Javascript
<script>
function computeCost(arr, N, X)
{
let cost = 0;
for (let i = 0; i < N; i++)
cost += Math.abs(arr[i] - X);
return cost;
}
function minCostToMakeElementEqual(arr, N)
{
let low, high;
low = high = arr[0];
for (let i = 0; i < N; i++) {
if (low > arr[i])
low = arr[i];
if (high < arr[i])
high = arr[i];
}
while ((high - low) > 2) {
let mid1 = low + (high - low) / 3;
let mid2 = high - (high - low) / 3;
let cost1 = computeCost(arr, N, mid1);
let cost2 = computeCost(arr, N, mid2);
if (cost1 < cost2)
high = mid2;
else
low = mid1;
}
return Math.round(computeCost(arr, N, (low + high) / 2));
}
let arr = [ 1, 100, 101 ];
let N = arr.length;
document.write(minCostToMakeElementEqual(arr, N));
</script>
|
PHP
<?php
function computeCost( $arr , $N , $X )
{
$cost = 0;
for ( $i = 0; $i < $N ; $i ++)
$cost += abs ( $arr [ $i ] - $X );
return $cost ;
}
function minCostToMakeElementEqual( $arr , $N )
{
$low ; $high ;
$low = $high = $arr [0];
for ( $i = 0; $i < $N ; $i ++)
{
if ( $low > $arr [ $i ])
$low = $arr [ $i ];
if ( $high < $arr [ $i ])
$high = $arr [ $i ];
}
while (( $high - $low ) > 2)
{
$mid1 = $low + ( floor ( $high - $low ) / 3);
$mid2 = $high - ( $high - $low ) / 3;
$cost1 = computeCost( $arr , $N , $mid1 );
$cost2 = computeCost( $arr , $N , $mid2 );
if ( $cost1 < $cost2 )
$high = $mid2 ;
else
$low = $mid1 ;
}
return computeCost( $arr , $N , ( $low +
$high ) / 2);
}
$arr = array ( 1, 100, 101 );
$N = sizeof( $arr ) / sizeof( $arr [0]);
echo minCostToMakeElementEqual( $arr , $N );
?>
|
Time Complexity: O(NlogN)
Auxiliary Space: O(1)
Alternate Solution
Think geometrically. Assume that array elements are co-ordinates on x axis. The problem reduces to finding another co-ordinate such that the sum of distances between this choice and other co-ordinates is minimized.
Observe that: If number of coordinates are odd then y = middle element. If even then y is any number in between middle 2 co-ordinates. Say Input = [a, b, c, d]. Output is any number between b and c including both. Hence the cost is sum which can be computed easily now that we have chosen y. sum|(y-ai)| for all i.
Below is the implementation of the above approach:
C++
#include <bits/stdc++.h>
using namespace std;
int minCostToMakeElementEqual( int a[], int n)
{
int y;
if (n % 2 == 1)
y = a[n / 2];
else
y = (a[n / 2] + a[(n - 2) / 2]) / 2;
int s = 0;
for ( int i = 0; i < n; i++)
s += abs (a[i] - y);
return s;
}
int main()
{
int a[] = { 1, 100, 101 };
int n = sizeof (a) / sizeof (a[0]);
sort(a, a + n);
cout << (minCostToMakeElementEqual(a, n));
}
|
Java
import java.io.*;
import java.util.*;
class GFG{
public static int minCostToMakeElementEqual( int a[],
int n)
{
int y;
if (n % 2 == 1 )
y = a[n / 2 ];
else
y = (a[n / 2 ] + a[(n - 2 ) / 2 ]) / 2 ;
int s = 0 ;
for ( int i = 0 ; i < n; i++)
s += Math.abs(a[i] - y);
return s;
}
public static void main (String[] args)
{
int a[] = { 1 , 100 , 101 };
Arrays.sort(a);
int n = a.length;
System.out.println(minCostToMakeElementEqual(a, n));
}
}
|
Python3
def minCostToMakeElementEqual(a):
l = len (a)
if (l % 2 = = 1 ):
y = a[l / / 2 ]
else :
y = (a[l / / 2 ] + a[(l - 2 ) / / 2 ]) / / 2
s = 0
for i in range (l):
s + = abs (a[i] - y)
return s
a = [ 1 , 1700 , 101 ]
a1 = sorted (a)
print (minCostToMakeElementEqual(a1))
|
C#
using System;
using System.Collections.Generic;
class GFG{
static int minCostToMakeElementEqual( int [] a,
int n)
{
int y;
if (n % 2 == 1)
y = a[n / 2];
else
y = (a[n / 2] + a[(n - 2) / 2]) / 2;
int s = 0;
for ( int i = 0; i < n; i++)
s += Math.Abs(a[i] - y);
return s;
}
static void Main()
{
int [] a = { 1, 100, 101 };
int n = a.Length;
Array.Sort(a);
Console.WriteLine(
minCostToMakeElementEqual(a, n));
}
}
|
Javascript
<script>
function minCostToMakeElementEqual( a, n)
{
let y;
if (n % 2 == 1)
y = a[(Math.trunc(n / 2))];
else
y = Math.trunc((a[n / 2] + a[(n - 2) / 2]) / 2);
let s = 0;
for (let i = 0; i < n; i++)
s += Math.abs(a[i] - y);
return s;
}
let a = [ 1, 1030, 1101 ];
let n = a.length;
a.sort((a1, b1) => a1 - b1);
document.write(minCostToMakeElementEqual(a, n));
</script>
|
Time Complexity: O(nlogn) – Since we are using sorting
Auxiliary Space: O(1)
This article is contributed by Utkarsh Trivedi. If you like GeeksforGeeks and would like to contribute, you can also write an article using write.geeksforgeeks.org or mail your article to review-team@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.
Please write comments if you find anything incorrect, or you want to share more information about the topic discussed above.