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 subarrayvoid 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 Codeint 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 subarraystatic 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 codepublic 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 subarraystatic 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 codepublic 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 subarrayfunction 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 Codevar 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)
Ready to dive in? Explore our Free Demo Content and join our DSA course, trusted by over 100,000 neveropen!
