Open In App

Maximize length of Non-Decreasing Subsequence by reversing at most one Subarray

Last Updated : 29 Mar, 2023
Comments
Improve
Suggest changes
Like Article
Like
Report

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

Output: 
4

 

Time Complexity: O(N) 
Auxiliary Space: O(N) <= O(4*N)
 


Next Article

Similar Reads