Longest alternating subsequence in terms of positive and negative integers
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++
#include <bits/stdc++.h>
using namespace std;
int LAS[1000][2] = { false };
int solve( int arr[], int n, int i, bool pos)
{
if (i == n)
return 0;
if (LAS[i][pos])
return LAS[i][pos];
int inc = 0, exc = 0;
if (arr[i] > 0 && pos == true ) {
pos = false ;
inc = 1 + solve(arr, n, i + 1, pos);
}
else if (arr[i] < 0 && pos == false ) {
pos = true ;
inc = 1 + solve(arr, n, i + 1, pos);
}
exc = solve(arr, n, i + 1, pos);
LAS[i][pos] = max(inc, exc);
return LAS[i][pos];
}
int main()
{
int arr[] = { -1, 2, 3, 4, 5,
-6, 8, -99 };
int n = sizeof (arr) / sizeof (arr[0]);
cout << max(solve(arr, n, 0, 0),
solve(arr, n, 0, 1));
}
|
Java
class GFG {
static int LAS[][] = new int [ 1000 ][ 2 ];
static int solve( int arr[], int n, int i, int pos)
{
if (i == n)
return 0 ;
if (LAS[i][pos]== 1 )
return LAS[i][pos];
int inc = 0 , exc = 0 ;
if (arr[i] > 0 && pos == 1 ) {
pos = 0 ;
inc = 1 + solve(arr, n, i + 1 , pos);
}
else if (arr[i] < 0 && pos == 0 ) {
pos = 1 ;
inc = 1 + solve(arr, n, i + 1 , pos);
}
exc = solve(arr, n, i + 1 , pos);
LAS[i][pos] = Math.max(inc, exc);
return LAS[i][pos];
}
public static void main (String[] args)
{
int arr[] = { - 1 , 2 , 3 , 4 , 5 , - 6 , 8 , - 99 };
int n = arr.length;
System.out.println(Math.max(solve(arr, n, 0 , 0 ),solve(arr, n, 0 , 1 )));
}
}
|
Python3
import numpy as np
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) :
if (i = = n) :
return 0 ;
if (LAS[i][pos]) :
return LAS[i][pos];
inc = 0 ; exc = 0 ;
if (arr[i] > 0 and pos = = True ) :
pos = False ;
inc = 1 + solve(arr, n, i + 1 , pos);
elif (arr[i] < 0 and pos = = False ) :
pos = True ;
inc = 1 + solve(arr, n, i + 1 , pos);
exc = solve(arr, n, i + 1 , pos);
LAS[i][pos] = max (inc, exc);
return LAS[i][pos];
if __name__ = = "__main__" :
arr = [ - 1 , 2 , 3 , 4 , 5 , - 6 , 8 , - 99 ];
n = len (arr);
print ( max (solve(arr, n, 0 , 0 ), solve(arr, n, 0 , 1 )));
|
C#
using System;
public class GFG {
static int [,]LAS = new int [1000,2];
static int solve( int []arr, int n, int i, int pos)
{
if (i == n)
return 0;
if (LAS[i,pos]== 1)
return LAS[i,pos];
int inc = 0, exc = 0;
if (arr[i] > 0 && pos == 1) {
pos = 0;
inc = 1 + solve(arr, n, i + 1, pos);
}
else if (arr[i] < 0 && pos == 0) {
pos = 1;
inc = 1 + solve(arr, n, i + 1, pos);
}
exc = solve(arr, n, i + 1, pos);
LAS[i,pos] = Math.Max(inc, exc);
return LAS[i,pos];
}
public static void Main()
{
int []arr = { -1, 2, 3, 4, 5, -6, 8, -99 };
int n = arr.Length;
Console.WriteLine(Math.Max(solve(arr, n, 0, 0),solve(arr, n, 0, 1)));
}
}
|
Javascript
<script>
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)
{
if (i == n)
return 0;
if (LAS[i][pos])
return LAS[i][pos];
let inc = 0, exc = 0;
if (arr[i] > 0 && pos == true ) {
pos = false ;
inc = 1 + solve(arr, n, i + 1, pos);
}
else if (arr[i] < 0 && pos == false ) {
pos = true ;
inc = 1 + solve(arr, n, i + 1, pos);
}
exc = solve(arr, n, i + 1, pos);
LAS[i][pos] = Math.max(inc, exc);
return LAS[i][pos];
}
let arr = [ -1, 2, 3, 4, 5,
-6, 8, -99 ];
let n = arr.length;
document.write(Math.max(solve(arr, n, 0, 0), solve(arr, n, 0, 1)));
</script>
|
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) {
int LAS[n][2];
LAS[0][0] = LAS[0][1] = 1;
for ( int i = 1; i < n; i++) {
LAS[i][0] = LAS[i][1] = 1;
for ( int j = 0; j < i; j++) {
if (arr[i] > 0 && arr[j] < 0 && LAS[i][0] < LAS[j][1] + 1) {
LAS[i][0] = LAS[j][1] + 1;
}
else if (arr[i] < 0 && arr[j] > 0 && LAS[i][1] < LAS[j][0] + 1) {
LAS[i][1] = LAS[j][0] + 1;
}
}
}
return max(LAS[n-1][0], LAS[n-1][1]);
}
int main() {
int arr[] = { -1, 2, 3, 4, 5, -6, 8, -99 };
int n = sizeof (arr) / sizeof (arr[0]);
cout << solve(arr, n);
}
|
Java
public class LongestAlternatingSubsequence {
public static int solve( int [] arr, int n) {
int [][] LAS = new int [n][ 2 ];
LAS[ 0 ][ 0 ] = LAS[ 0 ][ 1 ] = 1 ;
for ( int i = 1 ; i < n; i++) {
LAS[i][ 0 ] = LAS[i][ 1 ] = 1 ;
for ( int j = 0 ; j < i; j++) {
if (arr[i] > 0 && arr[j] < 0 && LAS[i][ 0 ] < LAS[j][ 1 ] + 1 ) {
LAS[i][ 0 ] = LAS[j][ 1 ] + 1 ;
}
else if (arr[i] < 0 && arr[j] > 0 && LAS[i][ 1 ] < LAS[j][ 0 ] + 1 ) {
LAS[i][ 1 ] = LAS[j][ 0 ] + 1 ;
}
}
}
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;
System.out.println(solve(arr, n));
}
}
|
Python3
def solve(arr, n):
LAS = [[ 1 , 1 ] for i in range (n)]
for i in range ( 1 , n):
for j in range (i):
if arr[i] > 0 and arr[j] < 0 and LAS[i][ 0 ] < LAS[j][ 1 ] + 1 :
LAS[i][ 0 ] = LAS[j][ 1 ] + 1
elif arr[i] < 0 and arr[j] > 0 and LAS[i][ 1 ] < LAS[j][ 0 ] + 1 :
LAS[i][ 1 ] = LAS[j][ 0 ] + 1
return max (LAS[n - 1 ][ 0 ], LAS[n - 1 ][ 1 ])
arr = [ - 1 , 2 , 3 , 4 , 5 , - 6 , 8 , - 99 ]
n = len (arr)
print (solve(arr, n))
|
C#
using System;
class Program {
static int Solve( int [] arr, int n)
{
int [, ] LAS = new int [n, 2];
LAS[0, 0] = LAS[0, 1] = 1;
for ( int i = 1; i < n; i++) {
LAS[i, 0] = LAS[i, 1] = 1;
for ( int j = 0; j < i; j++) {
if (arr[i] > 0 && arr[j] < 0
&& LAS[i, 0] < LAS[j, 1] + 1) {
LAS[i, 0] = LAS[j, 1] + 1;
}
else if (arr[i] < 0 && arr[j] > 0
&& LAS[i, 1] < LAS[j, 0] + 1) {
LAS[i, 1] = LAS[j, 0] + 1;
}
}
}
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;
Console.WriteLine(Solve(arr, n));
}
}
|
Javascript
function solve(arr) {
let n = arr.length;
let LAS = Array.from(Array(n), () => new Array(2));
LAS[0][0] = LAS[0][1] = 1;
for (let i = 1; i < n; i++) {
LAS[i][0] = LAS[i][1] = 1;
for (let j = 0; j < i; j++) {
if (arr[i] > 0 && arr[j] < 0 && LAS[i][0] < LAS[j][1] + 1) {
LAS[i][0] = LAS[j][1] + 1;
}
else if (arr[i] < 0 && arr[j] > 0 && LAS[i][1] < LAS[j][0] + 1) {
LAS[i][1] = LAS[j][0] + 1;
}
}
}
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)
Last Updated :
02 Oct, 2023
Like Article
Save Article
Share your thoughts in the comments
Please Login to comment...