Prerequisite: Sliding Window Median
Given an array arr[] consisting of N integers and an integer K, the task is to find the minimum cost required to make each element of every subarray of length K equal. Cost of replacing any array element by another element is the absolute difference between the two.
Examples:
Input: A[] = {1, 2, 3, 4, 6}, K = 3
Output: 7
Explanation:
Subarray 1: Cost to convert subarray {1, 2, 3} to {2, 2, 2} = |1-2| + |2-2| + |3-2| = 2
Subarray 2: Cost to convert subarray {2, 3, 4} to {3, 3, 3} = |2-3| + |3-3| + |4-3| = 2
Subarray 3: Cost to convert subarray {3, 4, 6} to {4, 4, 4} = |3-4| + |4-4| + |6-4| = 3
Minimum Cost = 2 + 2 + 3 = 7/
Input: A[] = {2, 3, 4, 4, 1, 7, 6}, K = 4
Output: 21
Approach:
To find the minimum cost to convert each element of the subarray to a single element, change every element of the subarray to the median of that subarray. Follow the steps below to solve the problem:
- To find the median for each running subarray efficiently, use a multiset to get the sorted order of elements in each subarray. Median will be the middle element of this multiset.
- For the next subarray remove the leftmost element of the previous subarray from the multiset, add the current element to the multiset.
- Keep a pointer mid to efficiently keep track of the middle element of the multiset.
- If the newly added element is smaller than the previous middle element, move mid to its immediate smaller element. Otherwise, move mid to its immediate next element.
- Calculate cost of replacing every element of the subarray by the equation | A[i] – medianeach_subarray |.
- Finally print the total cost.
Below is the implementation for the above approach:
// C++ Program to implement // the above approach #include <bits/stdc++.h> using namespace std;
// Function to find the minimum // cost to convert each element of // every subarray of size K equal int minimumCost(vector< int > arr, int n,
int k)
{ // Stores the minimum cost
int totalcost = 0;
int i, j;
// Stores the first K elements
multiset< int > mp(arr.begin(),
arr.begin() + k);
if (k == n) {
// Obtain the middle element of
// the multiset
auto mid = next(mp.begin(),
n / 2 - ((k + 1) % 2));
int z = *mid;
// Calculate cost for the subarray
for (i = 0; i < n; i++)
totalcost += abs (z - arr[i]);
// Return the total cost
return totalcost;
}
else {
// Obtain the middle element
// in multiset
auto mid = next(mp.begin(),
k / 2 - ((k + 1) % 2));
for (i = k; i < n; i++) {
int zz = *mid;
int cost = 0;
for (j = i - k; j < i; j++) {
// Cost for the previous
// k length subarray
cost += abs (arr[j] - zz);
}
totalcost += cost;
// Insert current element
// into multiset
mp.insert(arr[i]);
if (arr[i] < *mid) {
// New element appears
// to the left of mid
mid--;
}
if (arr[i - k] <= *mid) {
// New element appears
// to the right of mid
mid++;
}
// Remove leftmost element
// from the window
mp.erase(mp.lower_bound(arr[i - k]));
// For last element
if (i == n - 1) {
zz = *mid;
cost = 0;
for (j = i - k + 1;
j <= i; j++) {
// Calculate cost for the subarray
cost += abs (zz - arr[j]);
}
totalcost += cost;
}
}
// Return the total cost
return totalcost;
}
} // Driver Code int main()
{ int N = 5, K = 3;
vector< int > A({ 1, 2, 3, 4, 6 });
cout << minimumCost(A, N, K);
} |
import java.util.*;
class GFG {
// Function to find the minimum
// cost to convert each element of
// every subarray of size K equal
static int minimumCost( int [] arr, int n, int k)
{
// Stores the minimum cost
int totalcost = 0 ;
int i = 0 , j = 0 ;
// Stores the first K elements
List<Integer> mp = new ArrayList<Integer>();
for ( int x = 0 ; x < k; x++) {
mp.add(arr[x]);
}
Collections.sort(mp);
if (k == n) {
// Obtain the middle element of
// the list
int mid = mp.get(n / 2 - ((k + 1 ) % 2 ));
int z = mid;
// Calculate cost for the subarray
for (i = 0 ; i < n; i++) {
totalcost += Math.abs(z - arr[i]);
}
// Return the total cost
return totalcost;
}
else {
// Obtain the middle element in the list
int mid = mp.get(k / 2 - ((k + 1 ) % 2 ));
for (i = k; i < n; i++) {
int zz = mid;
int cost = 0 ;
for (j = i - k; j < i; j++) {
// Cost for the previous
// k length subarray
cost += Math.abs(arr[j] - zz);
}
totalcost += cost;
// Insert current element
// into the list
int idx
= Collections.binarySearch(mp, arr[i]);
if (idx < 0 ) {
mp.add(-idx - 1 , arr[i]);
}
else {
mp.add(idx, arr[i]);
}
if (arr[i] < mid) {
// New element appears
// to the left of mid
mid = mp.get(k / 2 - ((k + 1 ) % 2 ));
}
if (arr[i - k] <= mid) {
// New element appears
// to the right of mid
mid = mp.get(k / 2 - ((k + 1 ) % 2 ) + 1 );
}
// Remove leftmost element
// from the window
idx = Collections.binarySearch(mp,
arr[i - k]);
if (idx >= 0 ) {
mp.remove(idx);
}
// For last element
if (i == n - 1 ) {
zz = mid;
cost = 0 ;
for (j = i - k + 1 ; j < i + 1 ; j++) {
// Calculate cost for the subarray
cost += Math.abs(zz - arr[j]);
}
totalcost += cost;
}
}
// Return the total cost
return totalcost;
}
}
// Driver Code
public static void main(String[] args)
{
int N = 5 , K = 3 ;
int [] A = { 1 , 2 , 3 , 4 , 6 };
System.out.println(minimumCost(A, N, K));
}
} // This code is contributed by phasing17. |
import bisect
# Function to find the minimum # cost to convert each element of # every subarray of size K equal def minimumCost(arr, n, k):
# Stores the minimum cost
totalcost = 0
i, j = 0 , 0
# Stores the first K elements
mp = sorted (arr[:k])
if k = = n:
# Obtain the middle element of
# the list
mid = mp[n / / 2 - ((k + 1 ) % 2 )]
z = mid
# Calculate cost for the subarray
for i in range (n):
totalcost + = abs (z - arr[i])
# Return the total cost
return totalcost
else :
# Obtain the middle element in the list
mid = mp[k / / 2 - ((k + 1 ) % 2 )]
for i in range (k, n):
zz = mid
cost = 0
for j in range (i - k, i):
# Cost for the previous
# k length subarray
cost + = abs (arr[j] - zz)
totalcost + = cost
# Insert current element
# into the list
bisect.insort(mp, arr[i])
if arr[i] < mid:
# New element appears
# to the left of mid
mid = mp[k / / 2 - ((k + 1 ) % 2 )]
if arr[i - k] < = mid:
# New element appears
# to the right of mid
mid = mp[k / / 2 - ((k + 1 ) % 2 ) + 1 ]
# Remove leftmost element
# from the window
idx = bisect.bisect_left(mp, arr[i - k])
mp.pop(idx)
# For last element
if i = = n - 1 :
zz = mid
cost = 0
for j in range (i - k + 1 , i + 1 ):
# Calculate cost for the subarray
cost + = abs (zz - arr[j])
totalcost + = cost
# Return the total cost
return totalcost
# Driver Code if __name__ = = '__main__' :
N, K = 5 , 3
A = [ 1 , 2 , 3 , 4 , 6 ]
print (minimumCost(A, N, K))
# This code is contributed by phasing17.
|
// Javascript program for the above approach // Function to find the minimum cost to convert each // element of every subarray of size K equal function minimumCost(arr, n, k) {
// Stores the minimum cost
let totalcost = 0;
let i = 0,
j = 0;
// Stores the first K elements
let mp = arr.slice(0, k).sort((a, b) => a - b);
if (k == n) {
// Obtain the middle element of the list
let mid = mp[(Math.floor(n / 2) - ((k + 1) % 2))];
let z = mid;
// Calculate cost for the subarray
for (let i = 0; i < n; i++) {
totalcost += Math.abs(z - arr[i]);
}
// Return the total cost
return totalcost;
} else {
// Obtain the middle element in the list
let mid = mp[(Math.floor(k / 2) - ((k + 1) % 2))];
for (let i = k; i < n; i++) {
let zz = mid;
let cost = 0;
for (let j = i - k; j < i; j++) {
// Cost for the previous k length subarray
cost += Math.abs(arr[j] - zz);
}
totalcost += cost;
// Insert current element into the list
mp.splice(bisect_left(mp, arr[i]), 0, arr[i]);
if (arr[i] < mid) {
// New element appears to the left of mid
mid = mp[(Math.floor(k / 2) - ((k + 1) % 2))];
}
if (arr[i - k] <= mid) {
// New element appears to the right of mid
mid = mp[(Math.floor(k / 2) - ((k + 1) % 2) + 1)];
}
// Remove leftmost element from the window
mp.splice(bisect_left(mp, arr[i - k]), 1);
// For last element
if (i == n - 1) {
zz = mid;
cost = 0;
for (let j = i - k + 1; j <= i; j++) {
// Calculate cost for the subarray
cost += Math.abs(zz - arr[j]);
}
totalcost += cost;
}
}
// Return the total cost
return totalcost;
}
} // Driver Code let N = 5, K = 3;
let A = [1, 2, 3, 4, 6]; console.log(minimumCost(A, N, K)); // Returns the index at which the element should be inserted into the sorted list function bisect_left(arr, x) {
let lo = 0,
hi = arr.length;
while (lo < hi) {
let mid = Math.floor((lo + hi) / 2);
if (arr[mid] < x) lo = mid + 1;
else hi = mid;
}
return lo;
} // contributed by adityasharmadev01 |
// C# Equivalent using System;
using System.Collections.Generic;
public class GFG
{ // Function to find the minimum
// cost to convert each element of
// every subarray of size K equal
static int minimumCost( int [] arr, int n, int k)
{
// Stores the minimum cost
int totalcost = 0;
int i = 0, j = 0;
// Stores the first K elements
List< int > mp = new List< int >();
for ( int x = 0; x < k; x++)
{
mp.Add(arr[x]);
}
mp.Sort();
if (k == n)
{
// Obtain the middle element of
// the list
int mid = mp[n / 2 - (k + 1) % 2];
int z = mid;
// Calculate cost for the subarray
for (i = 0; i < n; i++)
{
totalcost += Math.Abs(z - arr[i]);
}
// Return the total cost
return totalcost;
}
else
{
// Obtain the middle element in the list
int mid = mp[k / 2 - (k + 1) % 2];
for (i = k; i < n; i++)
{
int zz = mid;
int cost = 0;
for (j = i - k; j < i; j++)
{
// Cost for the previous
// k length subarray
cost += Math.Abs(arr[j] - zz);
}
totalcost += cost;
// Insert current element
// into the list
int idx = mp.BinarySearch(arr[i]);
if (idx < 0)
{
mp.Insert(-idx - 1, arr[i]);
}
else
{
mp.Insert(idx, arr[i]);
}
if (arr[i] < mid)
{
// New element appears
// to the left of mid
mid = mp[k / 2 - (k + 1) % 2];
}
if (arr[i - k] <= mid)
{
// New element appears
// to the right of mid
mid = mp[k / 2 - (k + 1) % 2 + 1];
}
// Remove leftmost element
// from the window
idx = mp.BinarySearch(arr[i - k]);
if (idx >= 0)
{
mp.RemoveAt(idx);
}
// For last element
if (i == n - 1)
{
zz = mid;
cost = 0;
for (j = i - k + 1; j < i + 1; j++)
{
// Calculate cost for the subarray
cost += Math.Abs(zz - arr[j]);
}
totalcost += cost;
}
}
// Return the total cost
return totalcost;
}
}
// Driver Code
public static void Main(String[] args)
{
int N = 5, K = 3;
int [] A = { 1, 2, 3, 4, 6 };
Console.Write(minimumCost(A, N, K));
}
} |
7
Time Complexity: O(NlogN)
Auxiliary Space: O(1)