Given an array arr[] of positive and negative numbers only. The task is to find the length of the longest alternating (means negative-positive-negative or positive-negative-positive) subsequence present in the array.
Examples:
Input: arr[] = {-4, 3, -5, 9, 10, 12, 2, -1}
Output: 5
Explanation:
The longest sequence is {-4, 3, -5, 9, -1}, which is of length 5. There can be many more subsequences of this length.Input: arr[] = {10, 12, 2, -1}
Output: 2
Explanation:
The longest sequence is {10, -1}, which is 2. There can be many more subsequences of this length.
Approach:
This problem can be solved using Dynamic Programming. It is a variation Longest Increasing Subsequence(LIS). The following are the steps:
- For including and excluding an element in the given array arr[] for LAS(Longest Alternative Subsequence), a variable pos is used, when pos = true means the current element needs to be positive and if pos = false then current element needs to be negative.
- If we include the current element, change the value of pos and recur for the next element because we need the next element of the opposite to the previously included element.
- Now LAS[i][pos] can be recursively written as:
- Base case: If the index called recursively is greater than the last element, then return 0, as there is no such element left to form LAS and if LAS[i][pos] is calculated, then return the value.
if(i == N) {
return 0;
}
if(LAS[i][pos]) {
return LAS[i][pos];
}
- Recursive call: If the base case is not met, then recursively call when current element is included and excluded, then find the maximum of those to find LAS at that index.
LAS[i][pos] = Longest Alternating Subsequence at index i by including or excluding that element for the value of pos,
LAS[i][pos] = max(1 + recursive_function(i+1, pos), recursive_function(i+1, pos));
- Return statement: At each recursive call(except the base case), return the value of LAS[i][pos].
return LAS[i][pos];
- The LAS for the given array arr[] is the maximum of LAS[0][0] and LAS[0][1].
Below is the implementation of the above approach:
C++
// C++ program to find the // length of longest alternate // subsequence #include <bits/stdc++.h> using namespace std; // LAS[i][pos] array to find // the length of LAS till // index i by including or // excluding element arr[i] // on the basis of value of pos int LAS[1000][2] = { false }; int solve( int arr[], int n, int i, bool pos) { // Base Case if (i == n) return 0; if (LAS[i][pos]) return LAS[i][pos]; int inc = 0, exc = 0; // If current element is // positive and pos is true // Include the current element // and change pos to false if (arr[i] > 0 && pos == true ) { pos = false ; // Recur for the next // iteration inc = 1 + solve(arr, n, i + 1, pos); } // If current element is // negative and pos is false // Include the current element // and change pos to true else if (arr[i] < 0 && pos == false ) { pos = true ; // Recur for the next // iteration inc = 1 + solve(arr, n, i + 1, pos); } // If current element is // excluded, recur for // next iteration exc = solve(arr, n, i + 1, pos); LAS[i][pos] = max(inc, exc); return LAS[i][pos]; } // Driver's Code int main() { int arr[] = { -1, 2, 3, 4, 5, -6, 8, -99 }; int n = sizeof (arr) / sizeof (arr[0]); // Print LAS cout << max(solve(arr, n, 0, 0), solve(arr, n, 0, 1)); } |
Java
// Java program to find the // length of longest alternate // subsequence class GFG { // LAS[i][pos] array to find // the length of LAS till // index i by including or // excluding element arr[i] // on the basis of value of pos static int LAS[][] = new int [ 1000 ][ 2 ]; static int solve( int arr[], int n, int i, int pos) { // Base Case if (i == n) return 0 ; if (LAS[i][pos]== 1 ) return LAS[i][pos]; int inc = 0 , exc = 0 ; // If current element is // positive and pos is 1 // Include the current element // and change pos to 0 if (arr[i] > 0 && pos == 1 ) { pos = 0 ; // Recur for the next // iteration inc = 1 + solve(arr, n, i + 1 , pos); } // If current element is // negative and pos is o // Include the current element // and change pos to 1 else if (arr[i] < 0 && pos == 0 ) { pos = 1 ; // Recur for the next // iteration inc = 1 + solve(arr, n, i + 1 , pos); } // If current element is // excluded, recur for // next iteration exc = solve(arr, n, i + 1 , pos); LAS[i][pos] = Math.max(inc, exc); return LAS[i][pos]; } // Driver's Code public static void main (String[] args) { int arr[] = { - 1 , 2 , 3 , 4 , 5 , - 6 , 8 , - 99 }; int n = arr.length; // Print LAS System.out.println(Math.max(solve(arr, n, 0 , 0 ),solve(arr, n, 0 , 1 ))); } } // This code is contributed by AnkitRai01 |
Python3
# Python3 program to find the # length of longest alternate # subsequence import numpy as np # LAS[i][pos] array to find # the length of LAS till # index i by including or # excluding element arr[i] # on the basis of value of pos LAS = np.zeros(( 1000 , 2 )) for i in range ( 1000 ) : for j in range ( 2 ) : LAS[i][j] = False def solve(arr, n, i, pos) : # Base Case if (i = = n) : return 0 ; if (LAS[i][pos]) : return LAS[i][pos]; inc = 0 ; exc = 0 ; # If current element is # positive and pos is true # Include the current element # and change pos to false if (arr[i] > 0 and pos = = True ) : pos = False ; # Recur for the next # iteration inc = 1 + solve(arr, n, i + 1 , pos); # If current element is # negative and pos is false # Include the current element # and change pos to true elif (arr[i] < 0 and pos = = False ) : pos = True ; # Recur for the next # iteration inc = 1 + solve(arr, n, i + 1 , pos); # If current element is # excluded, recur for # next iteration exc = solve(arr, n, i + 1 , pos); LAS[i][pos] = max (inc, exc); return LAS[i][pos]; # Driver's Code if __name__ = = "__main__" : arr = [ - 1 , 2 , 3 , 4 , 5 , - 6 , 8 , - 99 ]; n = len (arr); # Print LAS print ( max (solve(arr, n, 0 , 0 ), solve(arr, n, 0 , 1 ))); # This code is contributed by AnkitRai01 |
C#
// C# program to find the // length of longest alternate // subsequence using System; public class GFG { // LAS[i][pos] array to find // the length of LAS till // index i by including or // excluding element arr[i] // on the basis of value of pos static int [,]LAS = new int [1000,2]; static int solve( int []arr, int n, int i, int pos) { // Base Case if (i == n) return 0; if (LAS[i,pos]== 1) return LAS[i,pos]; int inc = 0, exc = 0; // If current element is // positive and pos is 1 // Include the current element // and change pos to 0 if (arr[i] > 0 && pos == 1) { pos = 0; // Recur for the next // iteration inc = 1 + solve(arr, n, i + 1, pos); } // If current element is // negative and pos is o // Include the current element // and change pos to 1 else if (arr[i] < 0 && pos == 0) { pos = 1; // Recur for the next // iteration inc = 1 + solve(arr, n, i + 1, pos); } // If current element is // excluded, recur for // next iteration exc = solve(arr, n, i + 1, pos); LAS[i,pos] = Math.Max(inc, exc); return LAS[i,pos]; } // Driver's Code public static void Main() { int []arr = { -1, 2, 3, 4, 5, -6, 8, -99 }; int n = arr.Length; // Print LAS Console.WriteLine(Math.Max(solve(arr, n, 0, 0),solve(arr, n, 0, 1))); } } // This code is contributed by AnkitRai01 |
Javascript
<script> // Javascript program to find the // length of longest alternate // subsequence // LAS[i][pos] array to find // the length of LAS till // index i by including or // excluding element arr[i] // on the basis of value of pos let LAS = new Array(); for (let i = 0; i < 1000; i++){ let temp = new Array() for (let j = 0; j < 2; j++){ temp.push([]) } LAS.push(temp); } for (let i = 0; i < 1000; i++){ for (let j = 0; j < 2; j++){ LAS[i][j] = false } } function solve(arr, n, i, pos) { // Base Case if (i == n) return 0; if (LAS[i][pos]) return LAS[i][pos]; let inc = 0, exc = 0; // If current element is // positive and pos is true // Include the current element // and change pos to false if (arr[i] > 0 && pos == true ) { pos = false ; // Recur for the next // iteration inc = 1 + solve(arr, n, i + 1, pos); } // If current element is // negative and pos is false // Include the current element // and change pos to true else if (arr[i] < 0 && pos == false ) { pos = true ; // Recur for the next // iteration inc = 1 + solve(arr, n, i + 1, pos); } // If current element is // excluded, recur for // next iteration exc = solve(arr, n, i + 1, pos); LAS[i][pos] = Math.max(inc, exc); return LAS[i][pos]; } // Driver's Code let arr = [ -1, 2, 3, 4, 5, -6, 8, -99 ]; let n = arr.length; // Print LAS document.write(Math.max(solve(arr, n, 0, 0), solve(arr, n, 0, 1))); // This code is contributed by _saurabh_jaiswal </script> |
5
Time Complexity: O(N) where N is the length of the array.
Auxiliary Space: O(n) for call stack
Another approach : Using DP Tabulation method ( Iterative approach )
In this approach we use DP to store computation of subproblems and get the desired output without the help of recursion.
Implementation steps:
- Create a 2D array LAS of size n x 2 to store the lengths of the longest alternating subsequences that end at each index in the array.
- Initialize LAS[0][0] and LAS[0][1] to 1, as the longest alternating subsequence ending at the first index is always of length 1.
- For each pair of indices, check if the subsequence ending at index i can be extended by adding the element at index j. If arr[i] is positive and arr[j] is negative, and if LAS[i][0] < LAS[j][1] + 1, update LAS[i][0] to LAS[j][1] + 1, since adding the element at index j to the subsequence ending at index j will result in a longer alternating subsequence ending at index i
- Similarly, if arr[i] is negative and arr[j] is positive, and if LAS[i][1] < LAS[j][0] + 1, update LAS[i][1] to LAS[j][0] + 1
- Once all possible pairs of indices have been considered, return the maximum value of LAS[n-1][0] and LAS[n-1][1], which represent the lengths of the longest alternating subsequences ending at the last index of the array.
Implementation:
C++
#include <bits/stdc++.h> using namespace std; int solve( int arr[], int n) { // Create a 2D array to store the length of the longest alternating subsequence ending at each index. // The first column stores the length of the longest alternating subsequence ending with a negative number. // The second column stores the length of the longest alternating subsequence ending with a positive number. int LAS[n][2]; // Initialize the first row of LAS to 1 since the subsequence containing only the first element has length 1. LAS[0][0] = LAS[0][1] = 1; // Iterate over the array and fill in the LAS array. for ( int i = 1; i < n; i++) { // Initialize the current row to 1 since the subsequence containing only the current element has length 1. LAS[i][0] = LAS[i][1] = 1; // Iterate over the previous elements in the array and update the LAS array. for ( int j = 0; j < i; j++) { // If the current element is positive and the previous element is negative, // update the length of the longest alternating subsequence ending with a negative number. if (arr[i] > 0 && arr[j] < 0 && LAS[i][0] < LAS[j][1] + 1) { LAS[i][0] = LAS[j][1] + 1; } // If the current element is negative and the previous element is positive, // update the length of the longest alternating subsequence ending with a positive number. else if (arr[i] < 0 && arr[j] > 0 && LAS[i][1] < LAS[j][0] + 1) { LAS[i][1] = LAS[j][0] + 1; } } } // Return the maximum length of the longest alternating subsequence ending with a negative or positive number. return max(LAS[n-1][0], LAS[n-1][1]); } // Driver's Code int main() { int arr[] = { -1, 2, 3, 4, 5, -6, 8, -99 }; int n = sizeof (arr) / sizeof (arr[0]); // Print the length of the longest alternating subsequence. cout << solve(arr, n); } |
Java
public class LongestAlternatingSubsequence { public static int solve( int [] arr, int n) { // Create a 2D array to store the length of the longest alternating subsequence. // The first column stores the length of the longest // alternating subsequence ending with a negative number. // The second column stores the length of the longest // alternating subsequence ending with a positive number. int [][] LAS = new int [n][ 2 ]; // Initialize the first row of LAS to 1 since the subsequence // containing only the first element has length 1. LAS[ 0 ][ 0 ] = LAS[ 0 ][ 1 ] = 1 ; // Iterate over the array and fill in the LAS array. for ( int i = 1 ; i < n; i++) { // Initialize the current row to 1 since the subsequence // containing only the current element has length 1. LAS[i][ 0 ] = LAS[i][ 1 ] = 1 ; // Iterate over the previous elements in the array and update the LAS array. for ( int j = 0 ; j < i; j++) { // If the current element is positive and the previous element is negative, // update the length of the longest alternating subsequence // ending with a negative number. if (arr[i] > 0 && arr[j] < 0 && LAS[i][ 0 ] < LAS[j][ 1 ] + 1 ) { LAS[i][ 0 ] = LAS[j][ 1 ] + 1 ; } // If the current element is negative and the previous element is positive, // update the length of the longest alternating subsequence ending // with a positive number. else if (arr[i] < 0 && arr[j] > 0 && LAS[i][ 1 ] < LAS[j][ 0 ] + 1 ) { LAS[i][ 1 ] = LAS[j][ 0 ] + 1 ; } } } // Return the maximum length of the longest alternating // subsequence ending with a negative or positive number. return Math.max(LAS[n - 1 ][ 0 ], LAS[n - 1 ][ 1 ]); } public static void main(String[] args) { int [] arr = { - 1 , 2 , 3 , 4 , 5 , - 6 , 8 , - 99 }; int n = arr.length; // Print the length of the longest alternating subsequence. System.out.println(solve(arr, n)); } } |
Python3
# code def solve(arr, n): # Create a 2D array to store the length of the longest alternating subsequence ending at each index. # The first column stores the length of the longest alternating subsequence ending with a negative number. # The second column stores the length of the longest alternating subsequence ending with a positive number. LAS = [[ 1 , 1 ] for i in range (n)] # Iterate over the array and fill in the LAS array. for i in range ( 1 , n): # Iterate over the previous elements in the array and update the LAS array. for j in range (i): # If the current element is positive and the previous element is negative, # update the length of the longest alternating subsequence ending with a negative number. if arr[i] > 0 and arr[j] < 0 and LAS[i][ 0 ] < LAS[j][ 1 ] + 1 : LAS[i][ 0 ] = LAS[j][ 1 ] + 1 # If the current element is negative and the previous element is positive, # update the length of the longest alternating subsequence ending with a positive number. elif arr[i] < 0 and arr[j] > 0 and LAS[i][ 1 ] < LAS[j][ 0 ] + 1 : LAS[i][ 1 ] = LAS[j][ 0 ] + 1 # Return the maximum length of the longest alternating subsequence ending with a negative or positive number. return max (LAS[n - 1 ][ 0 ], LAS[n - 1 ][ 1 ]) # Driver's Code arr = [ - 1 , 2 , 3 , 4 , 5 , - 6 , 8 , - 99 ] n = len (arr) # Print the length of the longest alternating subsequence. print (solve(arr, n)) |
C#
using System; class Program { static int Solve( int [] arr, int n) { // Create a 2D array to store the length of the // longest alternating subsequence ending at each // index. The first column stores the length of the // longest alternating subsequence ending with a // negative number. The second column stores the // length of the longest alternating subsequence // ending with a positive number. int [, ] LAS = new int [n, 2]; // Initialize the first row of LAS to 1 since the // subsequence containing only the first element has // length 1. LAS[0, 0] = LAS[0, 1] = 1; // Iterate over the array and fill in the LAS array. for ( int i = 1; i < n; i++) { // Initialize the current row to 1 since the // subsequence containing only the current // element has length 1. LAS[i, 0] = LAS[i, 1] = 1; // Iterate over the previous elements in the // array and update the LAS array. for ( int j = 0; j < i; j++) { // If the current element is positive and // the previous element is negative, update // the length of the longest alternating // subsequence ending with a negative // number. if (arr[i] > 0 && arr[j] < 0 && LAS[i, 0] < LAS[j, 1] + 1) { LAS[i, 0] = LAS[j, 1] + 1; } // If the current element is negative and // the previous element is positive, update // the length of the longest alternating // subsequence ending with a positive // number. else if (arr[i] < 0 && arr[j] > 0 && LAS[i, 1] < LAS[j, 0] + 1) { LAS[i, 1] = LAS[j, 0] + 1; } } } // Return the maximum length of the longest // alternating subsequence ending with a negative or // positive number. return Math.Max(LAS[n - 1, 0], LAS[n - 1, 1]); } static void Main() { int [] arr = { -1, 2, 3, 4, 5, -6, 8, -99 }; int n = arr.Length; // Print the length of the longest alternating // subsequence. Console.WriteLine(Solve(arr, n)); } } // This code is contributed by sarojmcy2e |
Javascript
function solve(arr) { let n = arr.length; // Create a 2D array to store the length of the longest alternating subsequence ending at each index. // The first column stores the length of the longest alternating subsequence ending with a negative number. // The second column stores the length of the longest alternating subsequence ending with a positive number. let LAS = Array.from(Array(n), () => new Array(2)); // Initialize the first row of LAS to 1 since the subsequence containing only the first element has length 1. LAS[0][0] = LAS[0][1] = 1; // Iterate over the array and fill in the LAS array. for (let i = 1; i < n; i++) { // Initialize the current row to 1 since the subsequence containing only the current element has length 1. LAS[i][0] = LAS[i][1] = 1; // Iterate over the previous elements in the array and update the LAS array. for (let j = 0; j < i; j++) { // If the current element is positive and the previous element is negative, // update the length of the longest alternating subsequence ending with a negative number. if (arr[i] > 0 && arr[j] < 0 && LAS[i][0] < LAS[j][1] + 1) { LAS[i][0] = LAS[j][1] + 1; } // If the current element is negative and the previous element is positive, // update the length of the longest alternating subsequence ending with a positive number. else if (arr[i] < 0 && arr[j] > 0 && LAS[i][1] < LAS[j][0] + 1) { LAS[i][1] = LAS[j][0] + 1; } } } // Return the maximum length of the longest alternating subsequence ending with a negative or positive number. return Math.max(LAS[n-1][0], LAS[n-1][1]); } let arr = [-1, 2, 3, 4, 5, -6, 8, -99]; console.log(solve(arr)); |
Output:
5
Time Complexity: O(N*N)
Auxiliary Space: O(N*N)
Ready to dive in? Explore our Free Demo Content and join our DSA course, trusted by over 100,000 neveropen!