Open In App
Related Articles

Clustering/Partitioning an array such that sum of square differences is minimum

Improve
Improve
Improve
Like Article
Like
Save Article
Save
Report issue
Report

Given an array of n numbers and a number k. We need to divide the array into k partitions (clusters) of the same or different lengths. For a given k, there can be one or more ways to make clusters (partitions). We define a function Cost(i) for the ith cluster, as the square of the difference between its first and last element. If the current cluster is 

S_x,S_{x+1},S_{x+2}.........,S_{x+len_i-1}

, where leni is the length of current cluster, then :

Cost_{i}={(S_{x+len_i-1}-S_x)}^{2}

Amongst all the possible kinds of partitions, we have to find the partition that will minimize the function, 

    $$f(x)=\sum_{i=1}^{k} Cost_{i}$$

Examples : 

Input : arr[] = {1, 5, 8, 10}
            k = 2
Output : 20  
Explanation : 
Consider clustering 4 elements 1, 5, 8, 10
into 2 clusters. There are three options:
1. S1 = 1, S2 = 5, 8, 10, with total cost 
02 + 52 = 25.

2. S1 = 1, 5, S2 = 8, 10, with total cost
42 + 22 = 20 

3. S1 = 1, 5, 8, S2 = 10, with total cost 
72 + 02 = 49 

So, the optimal clustering is the second one, 

so the output of the above problem is 20.
Input : arr[] = {5, 8, 1, 10}
            k = 3

Output : 
9 
Explanation :
The three partitions are {5, 8}, {1} and {10}

To solve the problem, we assume that we have k slabs. We have to insert them in some k different positions in the array, which will give us the required partition scheme, and the one having a minimum value for f(x) will be the answer.

Naive solution: If we solve the above problem by the naive method, we would simply take all the possibilities and compute the minimum.

Implementation:

C++

// C++ program to find minimum cost k partitions
// of array.
#include<iostream>
using namespace std;
  
// Initialize answer as infinite.
const int inf = 1000000000;
int ans = inf;
  
// function to generate all possible answers.
// and compute minimum of all costs.
// i   --> is index of previous partition
// par --> is current number of partitions
// a[] and n --> Input array and its size
// current_ans --> Cost of partitions made so far.
void solve(int i, int par, int a[], int n,
                  int k, int current_ans)
{
    // If number of partitions is more than k
    if (par > k)
        return;
  
    // If we have made k partitions and have
    // reached last element
    if (par==k && i==n-1)
    {
        ans = min(ans, current_ans);
        return;
    }
  
    // 1) Partition array at different points
    // 2) For every point, increase count of 
    //    partitions, "par" by 1.
    // 3) Before recursive call, add cost of 
    //    the partition to current_ans
    for (int j=i+1; j<n; j++)
        solve(j, par+1, a, n, k, current_ans +
                  (a[j]-a[i+1])*(a[j]-a[i+1]));
}
  
// Driver code
int main()
{
    int k = 2;
    int a[] = {1, 5, 8, 10};
    int n = sizeof(a)/sizeof(a[0]);
    solve(-1, 0, a, n, k, 0);
    cout << ans << endl;
    return 0;
}

                    

Java

// Java program to find minimum cost k partitions
// of array.
import java.io.*;
  
class GFG
{
    // Initialize answer as infinite.
    static int inf = 1000000000;
    static int ans = inf;
      
    // function to generate all possible answers.
    // and compute minimum of all costs.
    // i --> is index of previous partition
    // par --> is current number of partitions
    // a[] and n --> Input array and its size
    // current_ans --> Cost of partitions made so far.
    static void solve(int i, int par, int a[], int n,
                               int k, int current_ans)
    {
        // If number of partitions is more than k
        if (par > k)
            return;
      
        // If we have made k partitions and have
        // reached last element
        if (par == k && i == n - 1)
        {
            ans = Math.min(ans, current_ans);
            return;
        }
      
        // 1) Partition array at different points
        // 2) For every point, increase count of 
        // partitions, "par" by 1.
        // 3) Before recursive call, add cost of 
        // the partition to current_ans
        for (int j = i + 1; j < n; j++)
            solve(j, par + 1, a, n, k, current_ans +
                 (a[j] - a[i + 1]) * (a[j] - a[i + 1]));
    }
      
    // Driver code
    public static void main (String[] args) 
    {
        int k = 2;
        int a[] = {1, 5, 8, 10};
        int n = a.length;
        solve(-1, 0, a, n, k, 0);
        System.out.println(ans);
          
    }
  
// This code is contributed by vt_m.

                    

Python3

# Python3 program to find minimum 
# cost k partitions of array.
  
# Initialize answer as infinite. 
inf = 1000000000
ans = inf
  
# function to generate all possible answers. 
# and compute minimum of all costs. 
# i --> is index of previous partition 
# par --> is current number of partitions 
# a[] and n --> Input array and its size 
# current_ans --> Cost of partitions made so far.
def solve(i, par, a, n, k, current_ans):
      
    # If number of partitions is more than k
    if (par > k):
        return 0
          
    # If we have made k partitions and 
    # have reached last element
    global ans
    if (par == k and i == n - 1):
        ans = min(ans, current_ans)
        return 0
  
    # 1) Partition array at different points 
    # 2) For every point, increase count of 
    # partitions, "par" by 1. 
    # 3) Before recursive call, add cost of 
    # the partition to current_ans 
    for j in range(i + 1, n):
        solve(j, par + 1, a, n, k, current_ans + 
             (a[j] - a[i + 1]) * (a[j] - a[i + 1]))
  
# Driver code 
k = 2
a = [1, 5, 8, 10]
n = len(a)
solve(-1, 0, a, n, k, 0)
print(ans)
  
# This code is contributed by sahilshelangia

                    

C#

// C# program to find minimum
// cost k partitions of array.
using System;
  
class GFG
{
    // Initialize answer as infinite.
    static int inf = 1000000000;
    static int ans = inf;
      
    // function to generate all possible answers.
    // and compute minimum of all costs.
    // i --> is index of previous partition
    // par --> is current number of partitions
    // a[] and n --> Input array and its size
    // current_ans --> Cost of partitions made so far.
    static void solve(int i, int par, int []a,
                      int n, int k, int current_ans)
    {
        // If number of partitions is more than k
        if (par > k)
            return;
      
        // If we have made k partitions and
        // have reached last element
        if (par == k && i == n - 1)
        {
            ans = Math.Min(ans, current_ans);
            return;
        }
      
        // 1) Partition array at different points
        // 2) For every point, increase count of 
        // partitions, "par" by 1.
        // 3) Before recursive call, add cost of 
        // the partition to current_ans
        for (int j = i + 1; j < n; j++)
            solve(j, par + 1, a, n, k, current_ans +
                 (a[j] - a[i + 1]) * (a[j] - a[i + 1]));
    }
      
    // Driver code
    public static void Main () 
    {
        int k = 2;
        int []a = {1, 5, 8, 10};
        int n = a.Length;
        solve(-1, 0, a, n, k, 0);
        Console.Write(ans);
    }
  
// This code is contributed by nitin mittal.

                    

PHP

<?php 
// PHP program to find minimum cost k 
// partitions of array.
  
// Initialize answer as infinite.
$inf = 1000000000;
$ans = $inf;
  
// function to generate all possible answers.
// and compute minimum of all costs.
// i --> is index of previous partition
// par --> is current number of partitions
// a[] and n --> Input array and its size
// current_ans --> Cost of partitions made so far.
function solve($i, $par, &$a, $n, $k, $current_ans)
{
    global $inf, $ans;
      
    // If number of partitions is 
    // more than k
    if ($par > $k)
        return;
  
    // If we have made k partitions and 
    // have reached last element
    if ($par == $k && $i == $n - 1)
    {
        $ans = min($ans, $current_ans);
        return;
    }
  
    // 1) Partition array at different points
    // 2) For every point, increase count of 
    //    partitions, "par" by 1.
    // 3) Before recursive call, add cost of 
    //    the partition to current_ans
    for ($j = $i + 1; $j < $n; $j++)
        solve($j, $par + 1, $a, $n, $k, $current_ans +
                           ($a[$j] - $a[$i + 1]) * 
                           ($a[$j] - $a[$i + 1]));
}
  
// Driver code
$k = 2;
$a = array(1, 5, 8, 10);
$n = sizeof($a);
solve(-1, 0, $a, $n, $k, 0);
echo $ans . "\n";
  
// This code is contributed by ita_c
?>

                    

Javascript

<script>
  
// Javascript program to find 
// minimum cost k partitions
// of array.
      
    // Initialize answer as infinite.
    let inf = 1000000000;
    let ans = inf;
      
    // function to generate all possible answers.
    // and compute minimum of all costs.
    // i --> is index of previous partition
    // par --> is current number of partitions
    // a[] and n --> Input array and its size
    // current_ans --> Cost of partitions made so far.
    function solve(i,par,a,n,k,current_ans)
    {
        // If number of partitions is more than k
        if (par > k)
            return;
       
        // If we have made k partitions and have
        // reached last element
        if (par == k && i == n - 1)
        {
            ans = Math.min(ans, current_ans);
            return;
        }
       
        // 1) Partition array at different points
        // 2) For every point, increase count of
        // partitions, "par" by 1.
        // 3) Before recursive call, add cost of
        // the partition to current_ans
        for (let j = i + 1; j < n; j++)
            solve(j, par + 1, a, n, k, current_ans +
                 (a[j] - a[i + 1]) * (a[j] - a[i + 1]));
    }
      
    // Driver code
    let k = 2;
    let a=[1, 5, 8, 10];
    let  n = a.length;
    solve(-1, 0, a, n, k, 0);
    document.write(ans);
      
      
    // This code is contributed by rag2127
      
</script>

                    

Output
20

Time Complexity: O(2n)

Space Complexity: O(n) where n is recursion stack space.

Dynamic Programming:

We create a table dp[n+1][k+1] table and initialize all values as infinite. 

dp[i][j] stores optimal partition cost 
         for arr[0..i-1] and j partitions.

Let us compute the value of dp[i][j]. we take an index m, such that m < i, and put a partition next to that position such that there is no slab in between the indices i and m. It can be seen simply that answer to the current scenario is dp[m][j-1] + (a[i-1]-a[m])*(a[i-1]-a[m]), where the first term signifies the minimum f(x) till the mth element with j-1 partitions and the second one signifies the cost of current cluster. So we will take the minimum of all the possible indices m and dp[i][j] will be assigned the minimum amongst them. 

Implementation:

C++

// C++ program to find minimum cost k partitions
// of array.
#include<iostream>
using namespace std;
const int inf = 1000000000;
  
// Returns minimum cost of partitioning a[] in
// k clusters.
int minCost(int a[], int n, int k)
{
    // Create a dp[][] table and initialize
    // all values as infinite. dp[i][j] is
    // going to store optimal partition cost
    // for arr[0..i-1] and j partitions
    int dp[n+1][k+1];
    for (int i=0; i<=n; i++)
        for (int j=0;j<=k;j++)
            dp[i][j] = inf;
  
    // Fill dp[][] in bottom up manner
    dp[0][0] = 0;
  
    // Current ending position (After i-th
    // iteration result for a[0..i-1] is computed.
    for (int i=1;i<=n;i++)
  
        // j is number of partitions
        for (int j=1;j<=k;j++)
  
            // Picking previous partition for
            // current i.
            for (int m=i-1;m>=0;m--)
                dp[i][j] = min(dp[i][j], dp[m][j-1] +
                          (a[i-1]-a[m])*(a[i-1]-a[m]));
  
  
    return dp[n][k];
}
  
// Driver code
int main()
{
    int k = 2;
    int a[] = {1, 5, 8, 10};
    int n = sizeof(a)/sizeof(a[0]);
    cout << minCost(a, n, k) << endl;
    return 0;
}

                    

Java

// Java program to find minimum cost 
// k partitions of array.
import java.io.*;
  
class GFG 
{
    static int inf = 1000000000;
      
    // Returns minimum cost of partitioning 
    // a[] in k clusters.
    static int minCost(int a[], int n, int k)
    {
        // Create a dp[][] table and initialize
        // all values as infinite. dp[i][j] is
        // going to store optimal partition cost
        // for arr[0..i-1] and j partitions
        int dp[][] = new int[n + 1][k + 1];
        for (int i = 0; i <= n; i++)
            for (int j = 0; j <= k; j++)
                dp[i][j] = inf;
      
        // Fill dp[][] in bottom up manner
        dp[0][0] = 0;
      
        // Current ending position (After i-th
        // iteration result for a[0..i-1] is computed.
        for (int i = 1; i <= n; i++)
      
            // j is number of partitions
            for (int j = 1; j <= k; j++)
      
                // Picking previous partition for
                // current i.
                for (int m = i - 1; m >= 0; m--)
                    dp[i][j] = Math.min(dp[i][j], dp[m][j - 1] +
                              (a[i - 1] - a[m]) * (a[i - 1] - a[m]));
      
      
        return dp[n][k];
    }
      
    // Driver code
    public static void main (String[] args) 
    {
        int k = 2;
        int a[] = {1, 5, 8, 10};
        int n = a.length;
        System.out.println(minCost(a, n, k));
              
    }
}
  
// This code is contributed by vt_m.

                    

Python3

# Python3 program to find minimum cost k partitions
# of array.
inf = 1000000000;
  
# Returns minimum cost of partitioning a[] in
# k clusters.
def minCost(a, n, k):
  
    # Create a dp[][] table and initialize
    # all values as infinite. dp[i][j] is
    # going to store optimal partition cost
    # for arr[0..i-1] and j partitions
    dp = [[inf for i in range(k + 1)] 
               for j in range(n + 1)];
  
    # Fill dp[][] in bottom up manner
    dp[0][0] = 0;
  
    # Current ending position (After i-th
    # iteration result for a[0..i-1] is computed.
    for i in range(1, n + 1):
  
        # j is number of partitions
        for j in range(1, k + 1):
  
            # Picking previous partition for
            # current i.
            for m in range(i - 1, -1, -1):
                dp[i][j] = min(dp[i][j], dp[m][j - 1] +
                                    (a[i - 1] - a[m]) * 
                                    (a[i - 1] - a[m]));
  
    return dp[n][k];
  
# Driver code
if __name__ == '__main__':
    k = 2;
    a = [1, 5, 8, 10];
    n = len(a);
    print(minCost(a, n, k));
  
# This code is contributed by 29AjayKumar

                    

C#

// C# program to find minimum cost 
// k partitions of array.
using System;
  
class GFG {
      
    static int inf = 1000000000;
      
    // Returns minimum cost of partitioning 
    // a[] in k clusters.
    static int minCost(int []a, int n, int k)
    {
          
        // Create a dp[][] table and initialize
        // all values as infinite. dp[i][j] is
        // going to store optimal partition cost
        // for arr[0..i-1] and j partitions
        int [,]dp = new int[n + 1,k + 1];
        for (int i = 0; i <= n; i++)
            for (int j = 0; j <= k; j++)
                dp[i,j] = inf;
      
        // Fill dp[][] in bottom
        // up manner
        dp[0,0] = 0;
      
        // Current ending position 
        // (After i-th iteration 
        // result for a[0..i-1]
        // is computed.
        for (int i = 1; i <= n; i++)
      
            // j is number of partitions
            for (int j = 1; j <= k; j++)
      
                // Picking previous
                // partition for
                // current i.
                for (int m = i - 1; m >= 0; m--)
                    dp[i,j] = Math.Min(dp[i,j],
                                 dp[m,j - 1] +
                               (a[i - 1] - a[m]) * 
                               (a[i - 1] - a[m]));
      
      
        return dp[n,k];
    }
      
    // Driver code
    public static void Main () 
    {
        int k = 2;
        int []a = {1, 5, 8, 10};
        int n = a.Length;
        Console.Write(minCost(a, n, k));
              
    }
}
  
// This code is contributed by nitin mittal

                    

Javascript

<script>
    // Javascript program to find minimum cost k partitions of array.
      
    let inf = 1000000000;
       
    // Returns minimum cost of partitioning
    // a[] in k clusters.
    function minCost(a, n, k)
    {
      
        // Create a dp[][] table and initialize
        // all values as infinite. dp[i][j] is
        // going to store optimal partition cost
        // for arr[0..i-1] and j partitions
        let dp = new Array(n + 1);
        for (let i = 0; i <= n; i++)
        {
            dp[i] = new Array(k + 1);
            for (let j = 0; j <= k; j++)
                dp[i][j] = inf;
        }
       
        // Fill dp[][] in bottom up manner
        dp[0][0] = 0;
       
        // Current ending position (After i-th
        // iteration result for a[0..i-1] is computed.
        for (let i = 1; i <= n; i++)
       
            // j is number of partitions
            for (let j = 1; j <= k; j++)
       
                // Picking previous partition for
                // current i.
                for (let m = i - 1; m >= 0; m--)
                    dp[i][j] = Math.min(dp[i][j], dp[m][j - 1] +
                              (a[i - 1] - a[m]) * (a[i - 1] - a[m]));
       
       
        return dp[n][k];
    }
      
    let k = 2;
    let a = [1, 5, 8, 10];
    let n = a.length;
    document.write(minCost(a, n, k));
  
// This code is contributed by rameshtravel07.
</script>

                    

Output
20

Time Complexity: O(k * n2)
Auxiliary Space: O(n*k)

This article is contributed by Amritya Vagmi and would like to contribute, you can also write an article using write.geeksforgeeks.org or mail your article to review-team@geeksforgeeks.org.  



Last Updated : 14 Sep, 2023
Like Article
Save Article
Previous
Next
Share your thoughts in the comments
Similar Reads