Maximize length of Non-Decreasing Subsequence by reversing at most one Subarray
Last Updated :
29 Mar, 2023
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++
// 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
// 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
# 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#
// 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
JavaScript
<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>
Time Complexity: O(N)
Auxiliary Space: O(N) <= O(4*N)
Similar Reads
Maximize subarray sum by inverting sign of elements of any subarray at most twice Given an array A of size n, find the maximum subarray sum after applying the given operation at most two times. In one operation, choose any two indices i and j and invert sign of all the elements from index i to index j, i.e, all positive elements in the range i to j become negative and all negativ
10 min read
Maximize non decreasing Array size by replacing Subarray with sum Given an array arr[] of size N. In one operation only one subarray can be selected and replaced with the sum of the subarray. The task is to find the maximum size of the array after making it non-decreasing.Examples:Input: N = 5, arr[] = {5, 1, 6, 6, 6}Output: 4Explanation: maximum size non-decreasi
15+ min read
Length of the longest increasing subsequence which does not contain a given sequence as Subarray Given two arrays arr[] and arr1[] of lengths N and M respectively, the task is to find the longest increasing subsequence of array arr[] such that it does not contain array arr1[] as subarray. Examples: Input: arr[] = {5, 3, 9, 3, 4, 7}, arr1[] = {3, 3, 7}Output: 4Explanation: Required longest incre
14 min read
Maximize product of a strictly increasing or decreasing subarray Given an array arr[] of size N, the task is to find the maximum product from any subarray consisting of elements in strictly increasing or decreasing order. Examples: Input: arr[] = { 1, 2, 10, 8, 1, 100, 101 } Output: 10100 Explanation: Increasing subarray with maximum product is {1, 100, 101}. The
14 min read
Find a subsequence which upon reversing gives the maximum sum subarray Given an array arr of integers of size N, the task is to find a subsequence in which upon reversing the order, the maximum sum subarray can be obtained. Examples: Input: arr[] = {-2, -3, 4, -1, -2, 1, 5, -3}Output: [-2 -3 1 5]Explanation : After selecting subsequence -2 -3 1 5 and reverse it element
6 min read