Open In App

Minimum increment or decrement operations required to make the array sorted

Improve
Improve
Like Article
Like
Save
Share
Report

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:
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:
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. 
 

  1. 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.
  2. 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.
  3. 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).
  4. 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) 
     
  5. Using the above recurrence relation and the base cases, the result can be easily calculated.

Below is the implementation of the above approach: 
 

C++




// C++ implementation of the approach
#include <bits/stdc++.h>
using namespace std;
 
// Function to return the minimum number
// of given operations required
// to sort the array
int getMinimumOps(vector<int> ar)
{
    // Number of elements in the array
    int n = ar.size();
 
    // Smallest element in the array
    int small = *min_element(ar.begin(), ar.end());
 
    // Largest element in the array
    int large = *max_element(ar.begin(), ar.end());
 
    /*
        dp(i, j) represents the minimum number
        of operations needed to make the
        array[0 .. i] sorted in non-decreasing
        order given that ith element is j
    */
    int dp[n][large + 1];
 
    // Fill the dp[]][ array for base cases
    for (int j = small; j <= large; j++) {
        dp[0][j] = abs(ar[0] - j);
    }
 
    /*
        Using results for the first (i - 1)
        elements, calculate the result
        for the ith element
    */
    for (int i = 1; i < n; i++) {
        int minimum = INT_MAX;
        for (int j = small; j <= large; j++) {
 
            /*
            If the ith element is j then we can have
            any value from small to j for the i-1 th
            element
            We choose the one that requires the
            minimum operations
        */
            minimum = min(minimum, dp[i - 1][j]);
            dp[i][j] = minimum + abs(ar[i] - j);
        }
    }
 
    /*
        If we made the (n - 1)th element equal to j
        we required dp(n-1, j) operations
        We choose the minimum among all possible
        dp(n-1, j) where j goes from small to large
    */
    int ans = INT_MAX;
    for (int j = small; j <= large; j++) {
        ans = min(ans, dp[n - 1][j]);
    }
 
    return ans;
}
 
// Driver code
int main()
{
    vector<int> ar = { 1, 2, 1, 4, 3 };
 
    cout << getMinimumOps(ar);
 
    return 0;
}


Java




// Java implementation of the approach
import java.util.*;
 
class GFG
{
 
// Function to return the minimum number
// of given operations required
// to sort the array
static int getMinimumOps(Vector<Integer> ar)
{
    // Number of elements in the array
    int n = ar.size();
 
    // Smallest element in the array
    int small = Collections.min(ar);
 
    // Largest element in the array
    int large = Collections.max(ar);
 
    /*
        dp(i, j) represents the minimum number
        of operations needed to make the
        array[0 .. i] sorted in non-decreasing
        order given that ith element is j
    */
    int [][]dp = new int[n][large + 1];
 
    // Fill the dp[]][ array for base cases
    for (int j = small; j <= large; j++)
    {
        dp[0][j] = Math.abs(ar.get(0) - j);
    }
 
    /*
        Using results for the first (i - 1)
        elements, calculate the result
        for the ith element
    */
    for (int i = 1; i < n; i++)
    {
        int minimum = Integer.MAX_VALUE;
        for (int j = small; j <= large; j++)
        {
 
            /*
            If the ith element is j then we can have
            any value from small to j for the i-1 th
            element
            We choose the one that requires the
            minimum operations
            */
            minimum = Math.min(minimum, dp[i - 1][j]);
            dp[i][j] = minimum + Math.abs(ar.get(i) - j);
        }
    }
 
    /*
        If we made the (n - 1)th element equal to j
        we required dp(n-1, j) operations
        We choose the minimum among all possible
        dp(n-1, j) where j goes from small to large
    */
    int ans = Integer.MAX_VALUE;
    for (int j = small; j <= large; j++)
    {
        ans = Math.min(ans, dp[n - 1][j]);
    }
    return ans;
}
 
// Driver code
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));
}
}
 
// This code is contributed by 29AjayKumar


Python3




# Python3 implementation of the approach
 
# Function to return the minimum number
# of given operations required
# to sort the array
def getMinimumOps(ar):
     
    # Number of elements in the array
    n = len(ar)
 
    # Smallest element in the array
    small = min(ar)
 
    # Largest element in the array
    large = max(ar)
 
    """
        dp(i, j) represents the minimum number
        of operations needed to make the
        array[0 .. i] sorted in non-decreasing
        order given that ith element is j
    """
    dp = [[ 0 for i in range(large + 1)]
              for i in range(n)]
 
    # Fill the dp[]][ array for base cases
    for j in range(small, large + 1):
        dp[0][j] = abs(ar[0] - j)
    """
    /*
        Using results for the first (i - 1)
        elements, calculate the result
        for the ith element
    */
    """
    for i in range(1, n):
        minimum = 10**9
        for j in range(small, large + 1):
             
        # """
        #     /*
        #     If the ith element is j then we can have
        #     any value from small to j for the i-1 th
        #     element
        #     We choose the one that requires the
        #     minimum operations
        # """
            minimum = min(minimum, dp[i - 1][j])
            dp[i][j] = minimum + abs(ar[i] - j)
    """
    /*
        If we made the (n - 1)th element equal to j
        we required dp(n-1, j) operations
        We choose the minimum among all possible
        dp(n-1, j) where j goes from small to large
    */
    """
    ans = 10**9
    for j in range(small, large + 1):
        ans = min(ans, dp[n - 1][j])
 
    return ans
 
# Driver code
ar = [1, 2, 1, 4, 3]
 
print(getMinimumOps(ar))
 
# This code is contributed by Mohit Kumar


C#




// C# implementation of the approach
using System;
using System.Linq;
using System.Collections.Generic;            
     
class GFG
{
 
// Function to return the minimum number
// of given operations required
// to sort the array
static int getMinimumOps(List<int> ar)
{
    // Number of elements in the array
    int n = ar.Count;
 
    // Smallest element in the array
    int small = ar.Min();
 
    // Largest element in the array
    int large = ar.Max();
 
    /*
        dp(i, j) represents the minimum number
        of operations needed to make the
        array[0 .. i] sorted in non-decreasing
        order given that ith element is j
    */
    int [,]dp = new int[n, large + 1];
 
    // Fill the dp[], array for base cases
    for (int j = small; j <= large; j++)
    {
        dp[0, j] = Math.Abs(ar[0] - j);
    }
 
    /*
        Using results for the first (i - 1)
        elements, calculate the result
        for the ith element
    */
    for (int i = 1; i < n; i++)
    {
        int minimum = int.MaxValue;
        for (int j = small; j <= large; j++)
        {
 
            /*
            If the ith element is j then we can have
            any value from small to j for the i-1 th
            element
            We choose the one that requires the
            minimum operations
            */
            minimum = Math.Min(minimum, dp[i - 1, j]);
            dp[i, j] = minimum + Math.Abs(ar[i] - j);
        }
    }
 
    /*
        If we made the (n - 1)th element equal to j
        we required dp(n-1, j) operations
        We choose the minimum among all possible
        dp(n-1, j) where j goes from small to large
    */
    int ans = int.MaxValue;
    for (int j = small; j <= large; j++)
    {
        ans = Math.Min(ans, dp[n - 1, j]);
    }
    return ans;
}
 
// Driver code
public static void Main(String[] args)
{
    int []arr = { 1, 2, 1, 4, 3 };
    List<int> ar = new List<int>(arr);
 
    Console.WriteLine(getMinimumOps(ar));
}
}
 
// This code is contributed by 29AjayKumar


Javascript




<script>
 
// Javascript implementation of the approach
 
// Function to return the minimum number
// of given operations required
// to sort the array
function getMinimumOps(ar)
{
    // Number of elements in the array
    var n = ar.length;
 
    // Smallest element in the array
    var small = Math.min.apply(Math,ar);
 
    // Largest element in the array
    var large = Math.max.apply(Math,ar);
 
    /*
        dp(i, j) represents the minimum number
        of operations needed to make the
        array[0 .. i] sorted in non-decreasing
        order given that ith element is j
    */
    var dp = new Array(n);
    var i,j;
    for(i=0;i<dp.length;i++)
        dp[i] = new Array(large+1);
 
    // Fill the dp[]][ array for base cases
    for (j = small; j <= large; j++) {
        dp[0][j] = Math.abs(ar[0] - j);
    }
 
    /*
        Using results for the first (i - 1)
        elements, calculate the result
        for the ith element
    */
    for (i = 1; i < n; i++) {
        var minimum = 2147483647;
        for (j = small; j <= large; j++) {
 
            /*
            If the ith element is j then we can have
            any value from small to j for the i-1 th
            element
            We choose the one that requires the
            minimum operations
        */
            minimum = Math.min(minimum, dp[i - 1][j]);
            dp[i][j] = minimum + Math.abs(ar[i] - j);
        }
    }
 
    /*
        If we made the (n - 1)th element equal to j
        we required dp(n-1, j) operations
        We choose the minimum among all possible
        dp(n-1, j) where j goes from small to large
    */
    var ans = 2147483647;
    for (j = small; j <= large; j++) {
        ans = Math.min(ans, dp[n - 1][j]);
    }
 
    return ans;
}
 
// Driver code
    var ar = [1, 2, 1, 4, 3];
 
    document.write(getMinimumOps(ar));
 
</script>


Output

2

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++




// C++ implementation of the approach
#include <bits/stdc++.h>
using namespace std;
 
// Function to return the minimum number
// of given operations required
// to sort the array
int getMinimumOps(vector<int> ar)
{  
    // Number of elements in the array
    int n = ar.size();
     
    // Smallest element in the array
    int small = *min_element(ar.begin(), ar.end());
 
    // Largest element in the array
    int large = *max_element(ar.begin(), ar.end());
     
    // create vector to store value of subproblems
    vector<int> dp(large + 1);
     
     
    // initialize base case
    for (int j = small; j <= large; j++) {
        dp[j] = abs(ar[0] - j);
    }
     
    // iterate iver subproblems to get the current
    // value from previous computations
    for (int i = 1; i < n; i++) {
        int minimum = INT_MAX; 
         
        // create vector to store current row values
        vector<int> curr(large + 1);
        for (int j = small; j <= large; j++) {
            minimum = min(minimum, dp[j]);
            curr[j] = minimum + abs(ar[i] - j);
        }
         
        // assigning values for further iterations
        dp = curr;
    }  
     
    // to store answer
    int ans = INT_MAX;
    for (int j = small; j <= large; j++) {
         
        // update answer
        ans = min(ans, dp[j]);
    }
     
    // return final answer
    return ans;
}
 
// Driver code
int main()
{
    vector<int> ar = { 1, 2, 1, 4, 3 };
     
    // function call
    cout << getMinimumOps(ar);
 
    return 0;
}


Java




import java.util.*;
 
public class Main {
 
  // Function to return the minimum number of given
  // operations required to sort the array
  public static int getMinimumOps(List<Integer> ar) {
 
    // Number of elements in the array
    int n = ar.size();
 
    // Smallest element in the array
    int small = Collections.min(ar);
 
    // Largest element in the array
    int large = Collections.max(ar);
 
    // create array to store value of subproblems
    int[] dp = new int[large + 1];
 
    // initialize base case
    for (int j = small; j <= large; j++) {
      dp[j] = Math.abs(ar.get(0) - j);
    }
 
    // iterate over subproblems to get the current value from previous computations
    for (int i = 1; i < n; i++) {
      int minimum = Integer.MAX_VALUE;
 
      // create array to store current row values
      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);
      }
 
      // assigning values for further iterations
      dp = curr;
    }
 
    // to store answer
    int ans = Integer.MAX_VALUE;
    for (int j = small; j <= large; j++) {
 
      // update answer
      ans = Math.min(ans, dp[j]);
    }
 
    // return final answer
    return ans;
  }
 
  // Driver code
  public static void main(String[] args) {
    List<Integer> ar = Arrays.asList(1, 2, 1, 4, 3);
 
    // function call
    System.out.println(getMinimumOps(ar));
  }
}


Python3




# Function to return the minimum number of operations required to sort the array
def getMinimumOps(ar):
    # Number of elements in the array
    n = len(ar)
 
    # Smallest element in the array
    small = min(ar)
 
    # Largest element in the array
    large = max(ar)
 
    # create list to store value of subproblems
    dp = [0] * (large + 1)
 
    # initialize base case
    for j in range(small, large + 1):
        dp[j] = abs(ar[0] - j)
 
    # iterate over subproblems to get the current value
    # from previous computations
    for i in range(1, n):
        minimum = float('inf')
 
        # create list to store current row values
        curr = [0] * (large + 1)
        for j in range(small, large + 1):
            minimum = min(minimum, dp[j])
            curr[j] = minimum + abs(ar[i] - j)
 
        # assigning values for further iterations
        dp = curr
 
    # to store answer
    ans = float('inf')
    for j in range(small, large + 1):
        # update answer
        ans = min(ans, dp[j])
 
    # return final answer
    return ans
 
# Driver code
ar = [1, 2, 1, 4, 3]
 
# function call
print(getMinimumOps(ar))


C#




using System;
using System.Collections.Generic;
using System.Linq;
 
class MainClass {
 
    // Function to return the minimum number
    // of given operations required to sort array
    public static int GetMinimumOps(List<int> ar)
    {
 
        // Number of elements in the array
        int n = ar.Count;
 
        // Smallest element in the array
        int small = ar.Min();
 
        // Largest element in the array
        int large = ar.Max();
 
        // create array to store value of subproblems
        int[] dp = new int[large + 1];
 
        // initialize base case
        for (int j = small; j <= large; j++) {
            dp[j] = Math.Abs(ar[0] - j);
        }
 
        // iterate over subproblems to get the
        // current value from previous computations
        for (int i = 1; i < n; i++) {
            int minimum = Int32.MaxValue;
 
            // create array to store current row values
            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);
            }
 
            // assigning values for further iterations
            dp = curr;
        }
 
        // to store answer
        int ans = Int32.MaxValue;
        for (int j = small; j <= large; j++) {
 
            // update answer
            ans = Math.Min(ans, dp[j]);
        }
 
        // return final answer
        return ans;
    }
 
    // Driver Code
    public static void Main()
    {
        List<int> ar = new List<int>() { 1, 2, 1, 4, 3 };
 
        // function call
        Console.WriteLine(GetMinimumOps(ar));
    }
}


Javascript




function getMinimumOps(ar) {
    // Number of elements in the array
    let n = ar.length;
     
    // Smallest element in the array
    let small = Math.min(...ar);
 
    // Largest element in the array
    let large = Math.max(...ar);
     
    // create array to store value of subproblems
    let dp = new Array(large + 1);
     
     
    // initialize base case
    for (let j = small; j <= large; j++) {
        dp[j] = Math.abs(ar[0] - j);
    }
     
    // iterate over subproblems to get the current
    // value from previous computations
    for (let i = 1; i < n; i++) {
        let minimum = Number.MAX_VALUE; 
         
        // create array to store current row values
        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);
        }
         
        // assigning values for further iterations
        dp = curr;
    }  
     
    // to store answer
    let ans = Number.MAX_VALUE;
    for (let j = small; j <= large; j++) {
         
        // update answer
        ans = Math.min(ans, dp[j]);
    }
     
    // return final answer
    return ans;
}
 
// Driver code
let ar = [1, 2, 1, 4, 3];
     
// function call
console.log(getMinimumOps(ar));


Output

2

Time Complexity: O(N*Large)
Auxiliary Space: O(Large)



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