Clustering/Partitioning an array such that sum of square differences is minimum
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
, where leni is the length of current cluster, then :
Amongst all the possible kinds of partitions, we have to find the partition that will minimize the function,
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.
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: It’s clear that the above algorithm has Time Complexity of O(2n)
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.
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: Having the three simple loops, the complexity of the above algorithm is O(n2k)
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. 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.