Minimum increment or decrement operations required to make the array sorted
Given an array arr[] of N integers, the task is to sort the array in non-decreasing order by performing the minimum number of operations. In a single operation, an element of the array can either be incremented or decremented by 1. Print the minimum number of operations required.
Examples:
Input: arr[] = {1, 2, 1, 4, 3}
Output: 2
Add 1 to the 3rd element(1) and subtract 1 from
the 4th element(4) to get {1, 2, 2, 3, 3}
Input: arr[] = {1, 2, 2, 100}
Output: 0
Given array is already sorted.
Observation: Since we would like to minimize the number of operations needed to sort the array the following should hold:
- A number will never be decreased to value lesser than the minimum of the initial array.
- A number will never be increased to a value greater than the maximum of the initial array.
- The number of operations required to change a number from X to Y is abs(X – Y).
Approach : Based on the above observation, this problem can be solved using dynamic programming.
- Let DP(i, j) represent the minimum operations needed to make the 1st i elements of the array sorted in non-decreasing order when the ith element is equal to j.
- Now DP(N, j) needs to be calculated for all possible values of j where N is the size of the array. According to the observations, j ? smallest element of the initial array and j ? the largest element of the initial array.
- The base cases in the DP(i, j) where i = 1 can be easily answered. What are the minimum operations needs to sort the 1st element in non-decreasing order such that the 1st element is equal to j?. DP(1, j) = abs( array[1] – j).
- Now consider DP(i, j) for i > 1. If ith element is set to j then the 1st i – 1 elements need to be sorted and the (i – 1)th element has to be ? j i.e. DP(i, j) = (minimum of DP(i – 1, k) where k goes from 1 to j) + abs(array[i] – j)
- Using the above recurrence relation and the base cases, the result can be easily calculated.
Below is the implementation of the above approach:
C++
#include <bits/stdc++.h>
using namespace std;
int getMinimumOps(vector< int > ar)
{
int n = ar.size();
int small = *min_element(ar.begin(), ar.end());
int large = *max_element(ar.begin(), ar.end());
int dp[n][large + 1];
for ( int j = small; j <= large; j++) {
dp[0][j] = abs (ar[0] - j);
}
for ( int i = 1; i < n; i++) {
int minimum = INT_MAX;
for ( int j = small; j <= large; j++) {
minimum = min(minimum, dp[i - 1][j]);
dp[i][j] = minimum + abs (ar[i] - j);
}
}
int ans = INT_MAX;
for ( int j = small; j <= large; j++) {
ans = min(ans, dp[n - 1][j]);
}
return ans;
}
int main()
{
vector< int > ar = { 1, 2, 1, 4, 3 };
cout << getMinimumOps(ar);
return 0;
}
|
Java
import java.util.*;
class GFG
{
static int getMinimumOps(Vector<Integer> ar)
{
int n = ar.size();
int small = Collections.min(ar);
int large = Collections.max(ar);
int [][]dp = new int [n][large + 1 ];
for ( int j = small; j <= large; j++)
{
dp[ 0 ][j] = Math.abs(ar.get( 0 ) - j);
}
for ( int i = 1 ; i < n; i++)
{
int minimum = Integer.MAX_VALUE;
for ( int j = small; j <= large; j++)
{
minimum = Math.min(minimum, dp[i - 1 ][j]);
dp[i][j] = minimum + Math.abs(ar.get(i) - j);
}
}
int ans = Integer.MAX_VALUE;
for ( int j = small; j <= large; j++)
{
ans = Math.min(ans, dp[n - 1 ][j]);
}
return ans;
}
public static void main(String[] args)
{
Integer []arr = { 1 , 2 , 1 , 4 , 3 };
Vector<Integer> ar = new Vector<>(Arrays.asList(arr));
System.out.println(getMinimumOps(ar));
}
}
|
Python3
def getMinimumOps(ar):
n = len (ar)
small = min (ar)
large = max (ar)
dp = [[ 0 for i in range (large + 1 )]
for i in range (n)]
for j in range (small, large + 1 ):
dp[ 0 ][j] = abs (ar[ 0 ] - j)
for i in range ( 1 , n):
minimum = 10 * * 9
for j in range (small, large + 1 ):
minimum = min (minimum, dp[i - 1 ][j])
dp[i][j] = minimum + abs (ar[i] - j)
ans = 10 * * 9
for j in range (small, large + 1 ):
ans = min (ans, dp[n - 1 ][j])
return ans
ar = [ 1 , 2 , 1 , 4 , 3 ]
print (getMinimumOps(ar))
|
C#
using System;
using System.Linq;
using System.Collections.Generic;
class GFG
{
static int getMinimumOps(List< int > ar)
{
int n = ar.Count;
int small = ar.Min();
int large = ar.Max();
int [,]dp = new int [n, large + 1];
for ( int j = small; j <= large; j++)
{
dp[0, j] = Math.Abs(ar[0] - j);
}
for ( int i = 1; i < n; i++)
{
int minimum = int .MaxValue;
for ( int j = small; j <= large; j++)
{
minimum = Math.Min(minimum, dp[i - 1, j]);
dp[i, j] = minimum + Math.Abs(ar[i] - j);
}
}
int ans = int .MaxValue;
for ( int j = small; j <= large; j++)
{
ans = Math.Min(ans, dp[n - 1, j]);
}
return ans;
}
public static void Main(String[] args)
{
int []arr = { 1, 2, 1, 4, 3 };
List< int > ar = new List< int >(arr);
Console.WriteLine(getMinimumOps(ar));
}
}
|
Javascript
<script>
function getMinimumOps(ar)
{
var n = ar.length;
var small = Math.min.apply(Math,ar);
var large = Math.max.apply(Math,ar);
var dp = new Array(n);
var i,j;
for (i=0;i<dp.length;i++)
dp[i] = new Array(large+1);
for (j = small; j <= large; j++) {
dp[0][j] = Math.abs(ar[0] - j);
}
for (i = 1; i < n; i++) {
var minimum = 2147483647;
for (j = small; j <= large; j++) {
minimum = Math.min(minimum, dp[i - 1][j]);
dp[i][j] = minimum + Math.abs(ar[i] - j);
}
}
var ans = 2147483647;
for (j = small; j <= large; j++) {
ans = Math.min(ans, dp[n - 1][j]);
}
return ans;
}
var ar = [1, 2, 1, 4, 3];
document.write(getMinimumOps(ar));
</script>
|
Complexity Analysis:
Time Complexity: O(N*R), Time complexity for the above approach is O(N * R) where N is the number of elements in the array and R = largest – smallest element of the array + 1.
Auxiliary Space: O(N * large)
Efficient approach : Space optimization
In previous approach the current value dp[i][j] is only depend upon the current and previous row values of DP. So to optimize the space complexity we use a single 1D array to store the computations.
Implementation steps:
- Create a 1D vector dp of size large+1.
- Set a base case by initializing the values of DP .
- Now iterate over subproblems by the help of nested loop and get the current value from previous computations.
- Now Create a 1d vector curr used to store the current values from previous computations.
- After every iteration assign the value of curr to dp for further iteration.
- Initialize a variable ans to store the final answer and update it by iterating through the Dp.
- At last return and print the final answer stored in ans .
Implementation:
C++
#include <bits/stdc++.h>
using namespace std;
int getMinimumOps(vector< int > ar)
{
int n = ar.size();
int small = *min_element(ar.begin(), ar.end());
int large = *max_element(ar.begin(), ar.end());
vector< int > dp(large + 1);
for ( int j = small; j <= large; j++) {
dp[j] = abs (ar[0] - j);
}
for ( int i = 1; i < n; i++) {
int minimum = INT_MAX;
vector< int > curr(large + 1);
for ( int j = small; j <= large; j++) {
minimum = min(minimum, dp[j]);
curr[j] = minimum + abs (ar[i] - j);
}
dp = curr;
}
int ans = INT_MAX;
for ( int j = small; j <= large; j++) {
ans = min(ans, dp[j]);
}
return ans;
}
int main()
{
vector< int > ar = { 1, 2, 1, 4, 3 };
cout << getMinimumOps(ar);
return 0;
}
|
Java
import java.util.*;
public class Main {
public static int getMinimumOps(List<Integer> ar) {
int n = ar.size();
int small = Collections.min(ar);
int large = Collections.max(ar);
int [] dp = new int [large + 1 ];
for ( int j = small; j <= large; j++) {
dp[j] = Math.abs(ar.get( 0 ) - j);
}
for ( int i = 1 ; i < n; i++) {
int minimum = Integer.MAX_VALUE;
int [] curr = new int [large + 1 ];
for ( int j = small; j <= large; j++) {
minimum = Math.min(minimum, dp[j]);
curr[j] = minimum + Math.abs(ar.get(i) - j);
}
dp = curr;
}
int ans = Integer.MAX_VALUE;
for ( int j = small; j <= large; j++) {
ans = Math.min(ans, dp[j]);
}
return ans;
}
public static void main(String[] args) {
List<Integer> ar = Arrays.asList( 1 , 2 , 1 , 4 , 3 );
System.out.println(getMinimumOps(ar));
}
}
|
Python3
def getMinimumOps(ar):
n = len (ar)
small = min (ar)
large = max (ar)
dp = [ 0 ] * (large + 1 )
for j in range (small, large + 1 ):
dp[j] = abs (ar[ 0 ] - j)
for i in range ( 1 , n):
minimum = float ( 'inf' )
curr = [ 0 ] * (large + 1 )
for j in range (small, large + 1 ):
minimum = min (minimum, dp[j])
curr[j] = minimum + abs (ar[i] - j)
dp = curr
ans = float ( 'inf' )
for j in range (small, large + 1 ):
ans = min (ans, dp[j])
return ans
ar = [ 1 , 2 , 1 , 4 , 3 ]
print (getMinimumOps(ar))
|
C#
using System;
using System.Collections.Generic;
using System.Linq;
class MainClass {
public static int GetMinimumOps(List< int > ar)
{
int n = ar.Count;
int small = ar.Min();
int large = ar.Max();
int [] dp = new int [large + 1];
for ( int j = small; j <= large; j++) {
dp[j] = Math.Abs(ar[0] - j);
}
for ( int i = 1; i < n; i++) {
int minimum = Int32.MaxValue;
int [] curr = new int [large + 1];
for ( int j = small; j <= large; j++) {
minimum = Math.Min(minimum, dp[j]);
curr[j] = minimum + Math.Abs(ar[i] - j);
}
dp = curr;
}
int ans = Int32.MaxValue;
for ( int j = small; j <= large; j++) {
ans = Math.Min(ans, dp[j]);
}
return ans;
}
public static void Main()
{
List< int > ar = new List< int >() { 1, 2, 1, 4, 3 };
Console.WriteLine(GetMinimumOps(ar));
}
}
|
Javascript
function getMinimumOps(ar) {
let n = ar.length;
let small = Math.min(...ar);
let large = Math.max(...ar);
let dp = new Array(large + 1);
for (let j = small; j <= large; j++) {
dp[j] = Math.abs(ar[0] - j);
}
for (let i = 1; i < n; i++) {
let minimum = Number.MAX_VALUE;
let curr = new Array(large + 1);
for (let j = small; j <= large; j++) {
minimum = Math.min(minimum, dp[j]);
curr[j] = minimum + Math.abs(ar[i] - j);
}
dp = curr;
}
let ans = Number.MAX_VALUE;
for (let j = small; j <= large; j++) {
ans = Math.min(ans, dp[j]);
}
return ans;
}
let ar = [1, 2, 1, 4, 3];
console.log(getMinimumOps(ar));
|
Time Complexity: O(N*Large)
Auxiliary Space: O(Large)
Last Updated :
14 Apr, 2023
Like Article
Save Article
Share your thoughts in the comments
Please Login to comment...