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++ 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 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 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# 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 |
<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:
#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);
} |
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));
}
} |
# 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))
|
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 |
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)