Minimize the sum of differences of consecutive elements after removing exactly K elements
Given a sorted array of length ‘N’ and an integer ‘K'(K<N), the task is to remove exactly ‘K’ elements from the array such that the sum of the difference of consecutive elements of the array is minimized.
Examples:
Input : arr[] = {1, 2, 3, 4}, k = 1
Output : 2
Let's consider all possible cases.
a) Remove 0th index: arr[] = {2, 3, 4}, ans = 2
b) Remove 1th index: arr[] = {1, 3, 4}, ans = 3
c) Remove 2nd index: arr[] = {1, 2, 4}, ans = 3
d) Remove 3th index: arr[] = {1, 2, 3}, ans = 2
Minimum of them all is 2, thus answer = 2
Input : arr[] = {1, 2, 10}, k = 1
Output : 1
Approach :
Removing elements from the ends is the only possible way to decrease the value of the sum.
For instance, let the array = {1, 2, 3, 4}. If the second element in the array is removed, then the sum stays the same as the previous i.e. equal to 3. But, if the first or the last element is removed, the sum decreases to 2.
Greedy Approach: At each step, removing that element which decreases the sum by a greater amount. For example, let the array = {1, 3, 9, 33}, 33 is removed as it reduces the sum to 8 from 32.
But, this greedy approach won’t work for certain test-cases. Example. arr[] = {1, 2, 100, 120, 140} and k = 2. Here, the final array of greedy approach is {1, 2, 100} where as the optimal array is {100, 120, 140}.
Dynamic Programming: The states of the DP are as follows:
DP[l][r] means the minimum sum you can achieve by removing the required number of elements in the sub-array arr[l to r].
Thus, the recurrence relation will be
DP[l][r] = min(DP[l][r-1], DP[l+1][r])
Below is the C++ implementation of the above idea.
C++
#include <bits/stdc++.h>
using namespace std;
#define N 100
#define INF 1000000
int dp[N][N];
bool vis[N][N];
int findSum( int * arr, int n, int k, int l, int r)
{
if ((l) + (n - 1 - r) == k)
return arr[r] - arr[l];
if (vis[l][r])
return dp[l][r];
vis[l][r] = 1;
return dp[l][r] = min(findSum(arr, n, k, l, r - 1),
findSum(arr, n, k, l + 1, r));
}
int32_t main()
{
int arr[] = { 1, 2, 100, 120, 140 };
int k = 2;
int n = sizeof (arr) / sizeof ( int );
cout << findSum(arr, n, k, 0, n - 1);
}
|
Java
class GFG
{
final static int N = 100 ;
final static int INF = 1000000 ;
static int dp[][] = new int [N][N];
static int vis[][] = new int [N][N];
static int findSum( int []arr, int n,
int k, int l, int r)
{
if ((l) + (n - 1 - r) == k)
return arr[r] - arr[l];
if (vis[l][r] == 1 )
return dp[l][r];
vis[l][r] = 1 ;
dp[l][r] = Math.min(findSum(arr, n, k, l, r - 1 ),
findSum(arr, n, k, l + 1 , r));
return dp[l][r] ;
}
public static void main (String[] args)
{
int arr[] = { 1 , 2 , 100 , 120 , 140 };
int k = 2 ;
int n = arr.length;
System.out.println(findSum(arr, n, k, 0 , n - 1 ));
}
}
|
Python3
import numpy as np
N = 100
INF = 1000000
dp = np.zeros((N, N));
vis = np.zeros((N, N));
def findSum(arr, n, k, l, r) :
if ((l) + (n - 1 - r) = = k) :
return arr[r] - arr[l];
if (vis[l][r]) :
return dp[l][r];
vis[l][r] = 1 ;
dp[l][r] = min (findSum(arr, n, k, l, r - 1 ),
findSum(arr, n, k, l + 1 , r));
return dp[l][r]
if __name__ = = "__main__" :
arr = [ 1 , 2 , 100 , 120 , 140 ];
k = 2 ;
n = len (arr);
print (findSum(arr, n, k, 0 , n - 1 ));
|
C#
using System;
class GFG
{
static int N = 100 ;
static int [,]dp = new int [N, N];
static int [,]vis = new int [N, N];
static int findSum( int []arr, int n,
int k, int l, int r)
{
if ((l) + (n - 1 - r) == k)
return arr[r] - arr[l];
if (vis[l, r] == 1)
return dp[l, r];
vis[l, r] = 1;
dp[l, r] = Math.Min(findSum(arr, n, k, l, r - 1),
findSum(arr, n, k, l + 1, r));
return dp[l, r] ;
}
public static void Main ()
{
int []arr = { 1, 2, 100, 120, 140 };
int k = 2;
int n = arr.Length;
Console.WriteLine(findSum(arr, n, k, 0, n - 1));
}
}
|
Javascript
<script>
var N = 100;
var INF = 1000000;
var dp = Array.from(Array(N), ()=> Array(N));
var vis = Array.from(Array(N), ()=> Array(N));
function findSum(arr, n, k, l, r)
{
if ((l) + (n - 1 - r) == k)
return arr[r] - arr[l];
if (vis[l][r])
return dp[l][r];
vis[l][r] = 1;
dp[l][r] = Math.min(findSum(arr, n, k, l, r - 1),
findSum(arr, n, k, l + 1, r));
return dp[l][r];
}
var arr = [1, 2, 100, 120, 140];
var k= 2;
var n = arr.length;
document.write( findSum(arr, n, k, 0, n - 1));
</script>
|
Time Complexity: O(n^2)
Space Complexity: O(n2) as 2d arrays like dp and vis has been created. Here n is size of the input array.
NOTE: An O(N) approach also exists for this problem. But the above-mentioned method can be used to solve the problem for unsorted arrays too with a little modification.
Alternate Approach:
Removing elements from left and right corner only. Therefore, if x elements are removed from the left, then K-x elements are removed from the right for every x in (0,K).
The sum of differences, if the above operation is performed, will be equal to arr[N-(K-X)-1] – arr[X].
On iterating the x from (0, K), the minimum value is picked among the obtained values.
Example:
Input: arr[] = {1, 3, 7, 8, 13} ; k = 3
Output: 1
Explanation:
Looping from X = 0 to X = K;
1) X = 0 and K-X = 3
So 0 elements removed from left and 3 from right.
array will be {1, 3} and answer will be 3 - 1 = 2.
min = 2
2) X = 1 and K-X = 2
So 1 elements removed from left and 2 from right.
array will be {3, 7} and answer will be 7 - 3 = 4.
min = 2
3) X = 2 and K-X = 1
So 2 elements removed from left and 1 from right.
array will be {7, 8} and answer will be 8 - 7 = 1.
min = 1
4) X = 3 and K-X = 0
So 3 elements removed from left and 0 from right.
array will be {8, 13} and answer will be 13 - 8 = 5.
min = 1
Below is the implementation of the above approach.
C++
#include <bits/stdc++.h>
using namespace std;
int findSum( int * arr, int n, int k)
{
int ans = arr[n - k - 1] - arr[0];
for ( int i = 1; i <= k; i++) {
ans = min(arr[n - 1 - (k - i)] - arr[i], ans);
}
return ans;
}
int32_t main()
{
int arr[] = { 1, 2, 100, 120, 140 };
int k = 2;
int n = sizeof (arr) / sizeof ( int );
cout << findSum(arr, n, k);
}
|
Java
class GFG
{
static int findSum( int []arr, int n, int k)
{
int ans = arr[n - k - 1 ] - arr[ 0 ];
for ( int i = 1 ; i <= k; i++)
{
ans = Math.min(arr[n - 1 - (k - i)] - arr[i], ans);
}
return ans;
}
public static void main (String[] args)
{
int arr[] = { 1 , 2 , 100 , 120 , 140 };
int k = 2 ;
int n = arr.length;
System.out.println(findSum(arr, n, k));
}
}
|
Python3
def findSum(arr, n, k) :
ans = arr[n - k - 1 ] - arr[ 0 ];
for i in range ( 1 , k + 1 ) :
ans = min (arr[n - 1 - (k - i)] - arr[i], ans);
return ans;
if __name__ = = "__main__" :
arr = [ 1 , 2 , 100 , 120 , 140 ];
k = 2 ;
n = len (arr);
print (findSum(arr, n, k));
|
C#
using System;
class GFG
{
static int findSum( int []arr, int n, int k)
{
int ans = arr[n - k - 1] - arr[0];
for ( int i = 1; i <= k; i++)
{
ans = Math.Min(arr[n - 1 - (k - i)] - arr[i], ans);
}
return ans;
}
public static void Main ()
{
int []arr = { 1, 2, 100, 120, 140 };
int k = 2;
int n = arr.Length;
Console.WriteLine(findSum(arr, n, k));
}
}
|
Javascript
<script>
function findSum(arr, n, k)
{
var ans = arr[n - k - 1] - arr[0];
for ( var i = 1; i <= k; i++) {
ans = Math.min(arr[n - 1 - (k - i)] - arr[i], ans);
}
return ans;
}
var arr = [1, 2, 100, 120, 140];
var k = 2;
var n = arr.length;
document.write( findSum(arr, n, k));
</script>
|
Time Complexity: O(n), where n is the size of the given array
Auxiliary Space: O(1), as no extra space is required
Last Updated :
17 Apr, 2023
Like Article
Save Article
Share your thoughts in the comments
Please Login to comment...