Given a binary array arr[], the task is to find the maximum possible length of non-decreasing subsequence that can be generated by reversing a subarray at most once.
Examples:
Input: arr[] = {0, 1, 0, 1}
Output: 4
Explanation:
After reversing the subarray from index [2, 3], the array modifies to {0, 0, 1, 1}.
Hence, the longest non-decreasing subsequence is {0, 0, 1, 1}.Input: arr[] = {0, 1, 1, 1, 0, 0, 1, 1, 0}
Output: 9
Explanation:
After reversing the subarray from index [2, 6], the array modifies to {0, 0, 0, 1, 1, 1, 1, 1, 0}.
Hence, the longest non-decreasing subsequence is {0, 0, 0, 1, 1, 1, 1, 1}.
Naive Approach: The simplest approach to solve the problem is to reverse each possible subarray in the given array, and find the longest non-decreasing subsequence possible from the array after reversing the subarray.
Time Complexity: O(N3)
Auxiliary Space: O(N)
Efficient Approach: The idea is to use Dynamic Programming to solve the problem. Follow the steps below:
- Since the array is a binary array the idea is to find the longest subsequence among the subsequences of the forms {0….0}, {0…1…}, {0..1..0…}, 0..1..0..1.
- Initialize a dynamic programming table as dp[][] which stores the following:
dp[i][0] : Stores the length of the longest subsequence (0..) from a[0 to i].
dp[i][1] : Stores the length of the longest subsequence (0..1..) from a[0 to i].
dp[i][2] : Stores the length of the longest subsequence (0..1..0..) from a[0 to i].
dp[i][3] : Stores the length of the longest subsequence (0..1..0..1..) from a[0 to i].
- Therefore, the answer is the longest subsequence or the maximum of all the 4 given possibilities ( dp[n-1][0], d[n-1][1], dp[n-1][2], dp[n-1][3] ).
Below is the implementation of the above approach:
// C++ program to implement // the above approach #include<bits/stdc++.h> using namespace std;
// Function to find the maximum length // non decreasing subarray by reversing // at most one subarray void main_fun( int arr[], int n)
{ // dp[i][j] be the longest
// subsequence of a[0...i]
// with first j parts
int dp[4][n];
memset (dp, 0, sizeof (dp[0][0] * 4 * n));
if (arr[0] == 0)
dp[0][0] = 1;
else
dp[1][0] = 1;
// Maximum length sub-sequence
// of (0..)
for ( int i = 1; i < n; i++)
{
if (arr[i] == 0)
dp[0][i] = dp[0][i - 1] + 1;
else
dp[0][i] = dp[0][i - 1];
}
// Maximum length sub-sequence
// of (0..1..)
for ( int i = 1; i < n; i++)
{
if (arr[i] == 1)
dp[1][i] = max(dp[1][i - 1] + 1,
dp[0][i - 1] + 1);
else
dp[1][i] = dp[1][i - 1];
}
// Maximum length sub-sequence
// of (0..1..0..)
for ( int i = 1; i < n; i++)
{
if (arr[i] == 0)
{
dp[2][i] = max(dp[2][i - 1] + 1,
max(dp[1][i - 1] + 1,
dp[0][i - 1] + 1));
}
else
dp[2][i] = dp[2][i - 1];
}
// Maximum length sub-sequence
// of (0..1..0..1..)
for ( int i = 1; i < n; i++)
{
if (arr[i] == 1)
{
dp[3][i] = max(dp[3][i - 1] + 1,
max(dp[2][i - 1] + 1,
max(dp[1][i - 1] + 1,
dp[0][i - 1] + 1)));
}
else
dp[3][i] = dp[3][i - 1];
}
// Find the max length subsequence
int ans = max(dp[2][n - 1], max(dp[1][n - 1],
max(dp[0][n - 1], dp[3][n - 1])));
// Print the answer
cout << (ans);
} // Driver Code int main()
{ int n = 4;
int arr[] = {0, 1, 0, 1};
main_fun(arr, n);
return 0;
} // This code is contributed by chitranayal |
// Java program to implement // the above approach import java.util.*;
class GFG{
// Function to find the maximum length // non decreasing subarray by reversing // at most one subarray static void main_fun( int arr[], int n)
{ // dp[i][j] be the longest
// subsequence of a[0...i]
// with first j parts
int [][] dp = new int [ 4 ][n];
if (arr[ 0 ] == 0 )
dp[ 0 ][ 0 ] = 1 ;
else
dp[ 1 ][ 0 ] = 1 ;
// Maximum length sub-sequence
// of (0..)
for ( int i = 1 ; i < n; i++)
{
if (arr[i] == 0 )
dp[ 0 ][i] = dp[ 0 ][i - 1 ] + 1 ;
else
dp[ 0 ][i] = dp[ 0 ][i - 1 ];
}
// Maximum length sub-sequence
// of (0..1..)
for ( int i = 1 ; i < n; i++)
{
if (arr[i] == 1 )
dp[ 1 ][i] = Math.max(dp[ 1 ][i - 1 ] + 1 ,
dp[ 0 ][i - 1 ] + 1 );
else
dp[ 1 ][i] = dp[ 1 ][i - 1 ];
}
// Maximum length sub-sequence
// of (0..1..0..)
for ( int i = 1 ; i < n; i++)
{
if (arr[i] == 0 )
{
dp[ 2 ][i] = Math.max(dp[ 2 ][i - 1 ] + 1 ,
Math.max(dp[ 1 ][i - 1 ] + 1 ,
dp[ 0 ][i - 1 ] + 1 ));
}
else
dp[ 2 ][i] = dp[ 2 ][i - 1 ];
}
// Maximum length sub-sequence
// of (0..1..0..1..)
for ( int i = 1 ; i < n; i++)
{
if (arr[i] == 1 )
{
dp[ 3 ][i] = Math.max(dp[ 3 ][i - 1 ] + 1 ,
Math.max(dp[ 2 ][i - 1 ] + 1 ,
Math.max(dp[ 1 ][i - 1 ] + 1 ,
dp[ 0 ][i - 1 ] + 1 )));
}
else
dp[ 3 ][i] = dp[ 3 ][i - 1 ];
}
// Find the max length subsequence
int ans = Math.max(dp[ 2 ][n - 1 ],
Math.max(dp[ 1 ][n - 1 ],
Math.max(dp[ 0 ][n - 1 ],
dp[ 3 ][n - 1 ])));
// Print the answer
System.out.print(ans);
} // Driver code public static void main (String[] args)
{ int n = 4 ;
int arr[] = { 0 , 1 , 0 , 1 };
main_fun(arr, n);
} } // This code is contributed by offbeat |
# Python3 program to implement # the above approach import sys
# Function to find the maximum length # non decreasing subarray by reversing # at most one subarray def main(arr, n):
# dp[i][j] be the longest
# subsequence of a[0...i]
# with first j parts
dp = [[ 0 for x in range (n)] for y in range ( 4 )]
if arr[ 0 ] = = 0 :
dp[ 0 ][ 0 ] = 1
else :
dp[ 1 ][ 0 ] = 1
# Maximum length sub-sequence
# of (0..)
for i in range ( 1 , n):
if arr[i] = = 0 :
dp[ 0 ][i] = dp[ 0 ][i - 1 ] + 1
else :
dp[ 0 ][i] = dp[ 0 ][i - 1 ]
# Maximum length sub-sequence
# of (0..1..)
for i in range ( 1 , n):
if arr[i] = = 1 :
dp[ 1 ][i] = max (dp[ 1 ][i - 1 ] + 1 , dp[ 0 ][i - 1 ] + 1 )
else :
dp[ 1 ][i] = dp[ 1 ][i - 1 ]
# Maximum length sub-sequence
# of (0..1..0..)
for i in range ( 1 , n):
if arr[i] = = 0 :
dp[ 2 ][i] = max ([dp[ 2 ][i - 1 ] + 1 ,
dp[ 1 ][i - 1 ] + 1 ,
dp[ 0 ][i - 1 ] + 1 ])
else :
dp[ 2 ][i] = dp[ 2 ][i - 1 ]
# Maximum length sub-sequence
# of (0..1..0..1..)
for i in range ( 1 , n):
if arr[i] = = 1 :
dp[ 3 ][i] = max ([dp[ 3 ][i - 1 ] + 1 ,
dp[ 2 ][i - 1 ] + 1 ,
dp[ 1 ][i - 1 ] + 1 ,
dp[ 0 ][i - 1 ] + 1 ])
else :
dp[ 3 ][i] = dp[ 3 ][i - 1 ]
# Find the max length subsequence
ans = max ([dp[ 2 ][n - 1 ], dp[ 1 ][n - 1 ],
dp[ 0 ][n - 1 ], dp[ 3 ][n - 1 ]])
# Print the answer
print (ans)
# Driver Code if __name__ = = "__main__" :
n = 4
arr = [ 0 , 1 , 0 , 1 ]
main(arr, n)
|
// C# program to implement // the above approach using System;
class GFG{
// Function to find the maximum length // non decreasing subarray by reversing // at most one subarray static void main_fun( int []arr, int n)
{ // dp[i,j] be the longest
// subsequence of a[0...i]
// with first j parts
int [,] dp = new int [4, n];
if (arr[0] == 0)
dp[0, 0] = 1;
else
dp[1, 0] = 1;
// Maximum length sub-sequence
// of (0..)
for ( int i = 1; i < n; i++)
{
if (arr[i] == 0)
dp[0, i] = dp[0, i - 1] + 1;
else
dp[0, i] = dp[0, i - 1];
}
// Maximum length sub-sequence
// of (0..1..)
for ( int i = 1; i < n; i++)
{
if (arr[i] == 1)
dp[1, i] = Math.Max(dp[1, i - 1] + 1,
dp[0, i - 1] + 1);
else
dp[1, i] = dp[1, i - 1];
}
// Maximum length sub-sequence
// of (0..1..0..)
for ( int i = 1; i < n; i++)
{
if (arr[i] == 0)
{
dp[2, i] = Math.Max(dp[2, i - 1] + 1,
Math.Max(dp[1, i - 1] + 1,
dp[0, i - 1] + 1));
}
else
dp[2, i] = dp[2, i - 1];
}
// Maximum length sub-sequence
// of (0..1..0..1..)
for ( int i = 1; i < n; i++)
{
if (arr[i] == 1)
{
dp[3, i] = Math.Max(dp[3, i - 1] + 1,
Math.Max(dp[2, i - 1] + 1,
Math.Max(dp[1, i - 1] + 1,
dp[0, i - 1] + 1)));
}
else
dp[3, i] = dp[3, i - 1];
}
// Find the max length subsequence
int ans = Math.Max(dp[2, n - 1],
Math.Max(dp[1, n - 1],
Math.Max(dp[0, n - 1],
dp[3, n - 1])));
// Print the answer
Console.Write(ans);
} // Driver code public static void Main(String[] args)
{ int n = 4;
int []arr = { 0, 1, 0, 1 };
main_fun(arr, n);
} } // This code is contributed by Amit Katiyar |
<script> // JavaScript program to implement // the above approach // Function to find the maximum length // non decreasing subarray by reversing // at most one subarray function main_fun(arr, n)
{ // dp[i][j] be the longest
// subsequence of a[0...i]
// with first j parts
var dp = Array.from(Array(4), ()=>Array(n).fill(0));
if (arr[0] == 0)
dp[0][0] = 1;
else
dp[1][0] = 1;
// Maximum length sub-sequence
// of (0..)
for ( var i = 1; i < n; i++)
{
if (arr[i] == 0)
dp[0][i] = dp[0][i - 1] + 1;
else
dp[0][i] = dp[0][i - 1];
}
// Maximum length sub-sequence
// of (0..1..)
for ( var i = 1; i < n; i++)
{
if (arr[i] == 1)
dp[1][i] = Math.max(dp[1][i - 1] + 1,
dp[0][i - 1] + 1);
else
dp[1][i] = dp[1][i - 1];
}
// Maximum length sub-sequence
// of (0..1..0..)
for ( var i = 1; i < n; i++)
{
if (arr[i] == 0)
{
dp[2][i] = Math.max(dp[2][i - 1] + 1,
Math.max(dp[1][i - 1] + 1,
dp[0][i - 1] + 1));
}
else
dp[2][i] = dp[2][i - 1];
}
// Maximum length sub-sequence
// of (0..1..0..1..)
for ( var i = 1; i < n; i++)
{
if (arr[i] == 1)
{
dp[3][i] = Math.max(dp[3][i - 1] + 1,
Math.max(dp[2][i - 1] + 1,
Math.max(dp[1][i - 1] + 1,
dp[0][i - 1] + 1)));
}
else
dp[3][i] = dp[3][i - 1];
}
// Find the max length subsequence
var ans = Math.max(dp[2][n - 1], Math.max(dp[1][n - 1],
Math.max(dp[0][n - 1], dp[3][n - 1])));
// Print the answer
document.write(ans);
} // Driver Code var n = 4;
var arr = [0, 1, 0, 1];
main_fun(arr, n); </script> |
4
Time Complexity: O(N)
Auxiliary Space: O(N) <= O(4*N)