Minimum increments to make the array non-decreasing
Last Updated :
08 Mar, 2024
Given an array A[] of size N along with an integer M such that 0 <= A[i] < M, the task is to output minimum number of operations required to sort A[] to non-decreasing order using following operation, choose an element let say A[i] and update it as (A[i] + 1) mod M.
Examples:
Input: N = 4, M = 5, A[] ={4, 1, 3, 2}
Output: 2
Explanation: The operations are performed as:
- Choose element A[0] = 4 and then update it as (A[0] + 1) mod 5 = (4 + 1) mod 5 = 0. Updated A[] = {0, 1, 3, 2}
- Choose element A[4] = 2 and then update it as (A[4] + 1) mod 5 = (2 + 1) mod 5 = 0. Updated A[] = {0, 1, 3, 3}
Now, it is visible that A[] is in non-decreasing order. Therefore, minimum number of operations required are 2.
Input: N = 5, M = 10, A = {0, 0, 1, 3, 7}
Output: 0
Explanation: A[] is already in non-decreasing order. Therefore, 0 operations are required.
Approach: To solve the problem, follow the below idea:
The problem can be solved using Dynamic Programming as at every index we have 2 choices to either apply the operation or don’t apply the operation. We can make a check by using previous value, if the current value is greater than the previous value, then we can explore both the cases of applying and not applying the operation. Else if the current value is less than the previous value, then we have to apply the operation. After exploring all the cases, choose the minimum of them.
Step-by-step algorithm:
- Create a 2D array, say DP[][], with all elements initialize to -1.
- Define a recursive function, Rec(curr_ele, Prev, A, M) to explore both the cases when we apply the operation and increment the current value and also when we don’t apply the operation.
- Declare a variable let say minOperations to store the minimum number of operations.
- Explore the first case when we apply the operation on the current index: (Prev – A[curr_index] + M) % M + Rec(curr_index + 1, Prev, A, M)
- Explore the second case when we don’t apply the operation: Rec(curr_index + 1, A[curr_index], A, M
- Store the min of both the cases in minOperations.
- Return DP[curr_index][Prev] as minOperations.
Below is the implementation of the algorithm:
C++
#include <bits/stdc++.h>
#include <iostream>
using namespace std;
int DP[1000][1000];
int Rec( int i, int prev, vector< int >& A, int M)
{
if (i == A.size())
return 0;
if (DP[i][prev] != -1)
return DP[i][prev];
int minOperations
= (prev - A[i] + M) % M + Rec(i + 1, prev, A, M);
if (A[i] >= prev)
minOperations
= min(Rec(i + 1, A[i], A, M), minOperations);
return DP[i][prev] = minOperations;
}
int minOperations( int N, int M, vector< int >& A)
{
memset (DP, -1, sizeof (DP));
return Rec(0, 0, A, M);
}
int main()
{
int N = 3;
int M = 2;
vector< int > A = { 4, 3, 2 };
cout << minOperations(N, M, A);
return 0;
}
|
Java
import java.util.Arrays;
import java.util.Vector;
public class GFG {
static int [][] DP = new int [ 1000 ][ 1000 ];
static int Rec( int i, int prev, Vector<Integer> A,
int M)
{
if (i == A.size())
return 0 ;
if (DP[i][prev] != - 1 )
return DP[i][prev];
int minOperations = (prev - A.get(i) + M) % M
+ Rec(i + 1 , prev, A, M);
if (A.get(i) >= prev)
minOperations = Math.min(
Rec(i + 1 , A.get(i), A, M), minOperations);
return DP[i][prev] = minOperations;
}
static int minOperations( int N, int M,
Vector<Integer> A)
{
for ( int [] row : DP)
Arrays.fill(row, - 1 );
return Rec( 0 , 0 , A, M);
}
public static void main(String[] args)
{
int N = 3 ;
int M = 2 ;
Vector<Integer> A
= new Vector<>(Arrays.asList( 4 , 3 , 2 ));
System.out.println(minOperations(N, M, A));
}
}
|
C#
using System;
class Program
{
static int [,] DP = new int [1000, 1000];
static int Rec( int i, int prev, int [] A, int M)
{
if (i == A.Length)
return 0;
if (DP[i, prev] != -1)
return DP[i, prev];
int minOperations = (prev - A[i] + M) % M + Rec(i + 1, prev, A, M);
if (A[i] >= prev)
minOperations = Math.Min(Rec(i + 1, A[i], A, M), minOperations);
return DP[i, prev] = minOperations;
}
static int MinOperations( int N, int M, int [] A)
{
for ( int i = 0; i < 1000; i++)
{
for ( int j = 0; j < 1000; j++)
{
DP[i, j] = -1;
}
}
return Rec(0, 0, A, M);
}
static void Main()
{
int N = 3;
int M = 2;
int [] A = { 4, 3, 2 };
Console.WriteLine(MinOperations(N, M, A));
}
}
|
Javascript
function rec(i, prev, A, M, DP) {
if (i === A.length)
return 0;
if (DP[i][prev] !== -1)
return DP[i][prev];
let minOperations = (prev - A[i] + M) % M
+ rec(i + 1, prev, A, M, DP);
if (A[i] >= prev)
minOperations = Math.min(
rec(i + 1, A[i], A, M, DP), minOperations);
DP[i][prev] = minOperations;
return DP[i][prev];
}
function minOperations(N, M, A) {
let DP = Array.from({ length: 1000 }, () => Array(1000).fill(-1));
return rec(0, 0, A, M, DP);
}
( function main() {
let N = 3;
let M = 2;
let A = [4, 3, 2];
console.log(minOperations(N, M, A));
})();
|
Python3
def rec(i, prev, A, M, DP):
if i = = len (A):
return 0
if DP[i][prev] ! = - 1 :
return DP[i][prev]
min_operations = (prev - A[i] + M) % M + rec(i + 1 , prev, A, M, DP)
if A[i] > = prev:
min_operations = min (rec(i + 1 , A[i], A, M, DP), min_operations)
DP[i][prev] = min_operations
return DP[i][prev]
def minOperations(N, M, A):
DP = [[ - 1 ] * 1000 for _ in range ( 1000 )]
return rec( 0 , 0 , A, M, DP)
if __name__ = = "__main__" :
N = 3
M = 2
A = [ 4 , 3 , 2 ]
print (minOperations(N, M, A))
|
Time Complexity: O(N*N), where N is the size of input array A[].
Auxiliary Space: O(N*N)
Share your thoughts in the comments
Please Login to comment...