Longest alternating subsequence
A sequence {X1, X2, .. Xn} is an alternating sequence if its elements satisfy one of the following relations :
X1 < X2 > X3 < X4 > X5 < …. xn or
X1 > X2 < X3 > X4 < X5 > …. xn
Examples:
Input: arr[] = {1, 5, 4}
Output: 3
Explanation: The whole arrays is of the form x1 < x2 > x3
Input: arr[] = {10, 22, 9, 33, 49, 50, 31, 60}
Output: 6
Explanation: The subsequences {10, 22, 9, 33, 31, 60} or
{10, 22, 9, 49, 31, 60} or {10, 22, 9, 50, 31, 60}
are longest subsequence of length 6
Note: This problem is an extension of the longest increasing subsequence problem, but requires more thinking for finding optimal substructure property in this
Longest alternating subsequence using dynamic programming:
To solve the problem follow the below idea:
We will solve this problem by dynamic Programming method, as it has optimal substructure and overlapping subproblems
Follow the below steps to solve the problem:
- Let A is given an array of length N
- We define a 2D array las[n][2] such that las[i][0] contains the longest alternating subsequence ending at index i and the last element is greater than its previous element
- las[i][1] contains the longest alternating subsequence ending at index i and the last element is smaller than its previous element, then we have the following recurrence relation between them,
las[i][0] = Length of the longest alternating subsequence
ending at index i and last element is greater
than its previous element
las[i][1] = Length of the longest alternating subsequence
ending at index i and last element is smaller
than its previous element
Recursive Formulation:
las[i][0] = max (las[i][0], las[j][1] + 1);
for all j < i and A[j] < A[i]
las[i][1] = max (las[i][1], las[j][0] + 1);
for all j < i and A[j] > A[i]
- The first recurrence relation is based on the fact that, If we are at position i and this element has to be bigger than its previous element then for this sequence (upto i) to be bigger we will try to choose an element j ( < i) such that A[j] < A[i] i.e. A[j] can become A[i]’s previous element and las[j][1] + 1 is bigger than las[i][0] then we will update las[i][0].
- Remember we have chosen las[j][1] + 1 not las[j][0] + 1 to satisfy the alternate property because in las[j][0] the last element is bigger than its previous one and A[i] is greater than A[j] which will break the alternating property if we update. So above fact derives the first recurrence relation, a similar argument can be made for the second recurrence relation also.
Below is the implementation of the above approach:
C++
#include <bits/stdc++.h>
using namespace std;
int max( int a, int b) { return (a > b) ? a : b; }
int zzis( int arr[], int n)
{
int las[n][2];
for ( int i = 0; i < n; i++)
las[i][0] = las[i][1] = 1;
int res = 1;
for ( int i = 1; i < n; i++) {
for ( int j = 0; j < i; j++) {
if (arr[j] < arr[i]
&& las[i][0] < las[j][1] + 1)
las[i][0] = las[j][1] + 1;
if (arr[j] > arr[i]
&& las[i][1] < las[j][0] + 1)
las[i][1] = las[j][0] + 1;
}
if (res < max(las[i][0], las[i][1]))
res = max(las[i][0], las[i][1]);
}
return res;
}
int main()
{
int arr[] = { 10, 22, 9, 33, 49, 50, 31, 60 };
int n = sizeof (arr) / sizeof (arr[0]);
cout << "Length of Longest alternating "
<< "subsequence is " << zzis(arr, n);
return 0;
}
|
C
#include <stdio.h>
#include <stdlib.h>
int max( int a, int b) { return (a > b) ? a : b; }
int zzis( int arr[], int n)
{
int las[n][2];
for ( int i = 0; i < n; i++)
las[i][0] = las[i][1] = 1;
int res = 1;
for ( int i = 1; i < n; i++) {
for ( int j = 0; j < i; j++) {
if (arr[j] < arr[i]
&& las[i][0] < las[j][1] + 1)
las[i][0] = las[j][1] + 1;
if (arr[j] > arr[i]
&& las[i][1] < las[j][0] + 1)
las[i][1] = las[j][0] + 1;
}
if (res < max(las[i][0], las[i][1]))
res = max(las[i][0], las[i][1]);
}
return res;
}
int main()
{
int arr[] = { 10, 22, 9, 33, 49, 50, 31, 60 };
int n = sizeof (arr) / sizeof (arr[0]);
printf (
"Length of Longest alternating subsequence is %d\n" ,
zzis(arr, n));
return 0;
}
|
Java
import java.io.*;
class GFG {
static int zzis( int arr[], int n)
{
int las[][] = new int [n][ 2 ];
for ( int i = 0 ; i < n; i++)
las[i][ 0 ] = las[i][ 1 ] = 1 ;
int res = 1 ;
for ( int i = 1 ; i < n; i++) {
for ( int j = 0 ; j < i; j++) {
if (arr[j] < arr[i]
&& las[i][ 0 ] < las[j][ 1 ] + 1 )
las[i][ 0 ] = las[j][ 1 ] + 1 ;
if (arr[j] > arr[i]
&& las[i][ 1 ] < las[j][ 0 ] + 1 )
las[i][ 1 ] = las[j][ 0 ] + 1 ;
}
if (res < Math.max(las[i][ 0 ], las[i][ 1 ]))
res = Math.max(las[i][ 0 ], las[i][ 1 ]);
}
return res;
}
public static void main(String[] args)
{
int arr[] = { 10 , 22 , 9 , 33 , 49 , 50 , 31 , 60 };
int n = arr.length;
System.out.println( "Length of Longest "
+ "alternating subsequence is "
+ zzis(arr, n));
}
}
|
Python3
def Max (a, b):
if a > b:
return a
else :
return b
def zzis(arr, n):
las = [[ 0 for i in range ( 2 )]
for j in range (n)]
for i in range (n):
las[i][ 0 ], las[i][ 1 ] = 1 , 1
res = 1
for i in range ( 1 , n):
for j in range ( 0 , i):
if (arr[j] < arr[i] and
las[i][ 0 ] < las[j][ 1 ] + 1 ):
las[i][ 0 ] = las[j][ 1 ] + 1
if (arr[j] > arr[i] and
las[i][ 1 ] < las[j][ 0 ] + 1 ):
las[i][ 1 ] = las[j][ 0 ] + 1
if (res < max (las[i][ 0 ], las[i][ 1 ])):
res = max (las[i][ 0 ], las[i][ 1 ])
return res
arr = [ 10 , 22 , 9 , 33 , 49 , 50 , 31 , 60 ]
n = len (arr)
print ( "Length of Longest alternating subsequence is" ,
zzis(arr, n))
|
C#
using System;
class GFG {
static int zzis( int [] arr, int n)
{
int [, ] las = new int [n, 2];
for ( int i = 0; i < n; i++)
las[i, 0] = las[i, 1] = 1;
int res = 1;
for ( int i = 1; i < n; i++) {
for ( int j = 0; j < i; j++) {
if (arr[j] < arr[i]
&& las[i, 0] < las[j, 1] + 1)
las[i, 0] = las[j, 1] + 1;
if (arr[j] > arr[i]
&& las[i, 1] < las[j, 0] + 1)
las[i, 1] = las[j, 0] + 1;
}
if (res < Math.Max(las[i, 0], las[i, 1]))
res = Math.Max(las[i, 0], las[i, 1]);
}
return res;
}
public static void Main()
{
int [] arr = { 10, 22, 9, 33, 49, 50, 31, 60 };
int n = arr.Length;
Console.WriteLine( "Length of Longest "
+ "alternating subsequence is "
+ zzis(arr, n));
}
}
|
PHP
<?php
function zzis( $arr , $n )
{
$las = array ( array ());
for ( $i = 0; $i < $n ; $i ++)
$las [ $i ][0] = $las [ $i ][1] = 1;
$res = 1;
for ( $i = 1; $i < $n ; $i ++)
{
for ( $j = 0; $j < $i ; $j ++)
{
if ( $arr [ $j ] < $arr [ $i ] and
$las [ $i ][0] < $las [ $j ][1] + 1)
$las [ $i ][0] = $las [ $j ][1] + 1;
if ( $arr [ $j ] > $arr [ $i ] and
$las [ $i ][1] < $las [ $j ][0] + 1)
$las [ $i ][1] = $las [ $j ][0] + 1;
}
if ( $res < max( $las [ $i ][0], $las [ $i ][1]))
$res = max( $las [ $i ][0], $las [ $i ][1]);
}
return $res ;
}
$arr = array (10, 22, 9, 33,
49, 50, 31, 60 );
$n = count ( $arr );
echo "Length of Longest alternating " .
"subsequence is " , zzis( $arr , $n ) ;
?>
|
Javascript
<script>
function zzis(arr, n)
{
let las = new Array(n);
for (let i = 0; i < n; i++)
{
las[i] = new Array(2);
for (let j = 0; j < 2; j++)
{
las[i][j] = 0;
}
}
for (let i = 0; i < n; i++)
las[i][0] = las[i][1] = 1;
let res = 1;
for (let i = 1; i < n; i++)
{
for (let j = 0; j < i; j++)
{
if (arr[j] < arr[i] &&
las[i][0] < las[j][1] + 1)
las[i][0] = las[j][1] + 1;
if ( arr[j] > arr[i] &&
las[i][1] < las[j][0] + 1)
las[i][1] = las[j][0] + 1;
}
if (res < Math.max(las[i][0], las[i][1]))
res = Math.max(las[i][0], las[i][1]);
}
return res;
}
let arr = [ 10, 22, 9, 33, 49, 50, 31, 60 ];
let n = arr.length;
document.write( "Length of Longest " +
"alternating subsequence is " +
zzis(arr, n));
</script>
|
Output
Length of Longest alternating subsequence is 6
Time Complexity: O(N2)
Auxiliary Space: O(N), since N extra space has been taken
Efficient Approach: To solve the problem follow the below idea:
In the above approach, at any moment we are keeping track of two values (The length of the longest alternating subsequence ending at index i, and the last element is smaller than or greater than the previous element), for every element on the array. To optimize space, we only need to store two variables for element at any index i
inc = Length of longest alternative subsequence so far with current value being greater than it’s previous value.
dec = Length of longest alternative subsequence so far with current value being smaller than it’s previous value.
The tricky part of this approach is to update these two values.
“inc” should be increased, if and only if the last element in the alternative sequence was smaller than it’s previous element.
“dec” should be increased, if and only if the last element in the alternative sequence was greater than it’s previous element.
Follow the below steps to solve the problem:
- Declare two integers inc and dec equal to one
- Run a loop for i [1, N-1]
- If arr[i] is greater than the previous element then set inc equal to dec + 1
- Else if arr[i] is smaller than the previous element then set dec equal to inc + 1
- Return maximum of inc and dec
Below is the implementation of the above approach:
C++
#include <bits/stdc++.h>
using namespace std;
int LAS( int arr[], int n)
{
int inc = 1;
int dec = 1;
for ( int i = 1; i < n; i++) {
if (arr[i] > arr[i - 1]) {
inc = dec + 1;
}
else if (arr[i] < arr[i - 1]) {
dec = inc + 1;
}
}
return max(inc, dec);
}
int main()
{
int arr[] = { 10, 22, 9, 33, 49, 50, 31, 60 };
int n = sizeof (arr) / sizeof (arr[0]);
cout << LAS(arr, n) << endl;
return 0;
}
|
Java
public class GFG {
static int LAS( int [] arr, int n)
{
int inc = 1 ;
int dec = 1 ;
for ( int i = 1 ; i < n; i++) {
if (arr[i] > arr[i - 1 ]) {
inc = dec + 1 ;
}
else if (arr[i] < arr[i - 1 ]) {
dec = inc + 1 ;
}
}
return Math.max(inc, dec);
}
public static void main(String[] args)
{
int [] arr = { 10 , 22 , 9 , 33 , 49 , 50 , 31 , 60 };
int n = arr.length;
System.out.println(LAS(arr, n));
}
}
|
Python3
def LAS(arr, n):
inc = 1
dec = 1
for i in range ( 1 , n):
if (arr[i] > arr[i - 1 ]):
inc = dec + 1
elif (arr[i] < arr[i - 1 ]):
dec = inc + 1
return max (inc, dec)
if __name__ = = "__main__" :
arr = [ 10 , 22 , 9 , 33 , 49 , 50 , 31 , 60 ]
n = len (arr)
print (LAS(arr, n))
|
C#
using System;
class GFG {
static int LAS( int [] arr, int n)
{
int inc = 1;
int dec = 1;
for ( int i = 1; i < n; i++) {
if (arr[i] > arr[i - 1]) {
inc = dec + 1;
}
else if (arr[i] < arr[i - 1]) {
dec = inc + 1;
}
}
return Math.Max(inc, dec);
}
static void Main()
{
int [] arr = { 10, 22, 9, 33, 49, 50, 31, 60 };
int n = arr.Length;
Console.WriteLine(LAS(arr, n));
}
}
|
Javascript
<script>
function LAS(arr, n)
{
let inc = 1;
let dec = 1;
for (let i = 1; i < n; i++)
{
if (arr[i] > arr[i - 1])
{
inc = dec + 1;
}
else if (arr[i] < arr[i - 1])
{
dec = inc + 1;
}
}
return Math.max(inc, dec);
}
let arr = [ 10, 22, 9, 33, 49, 50, 31, 60 ];
let n = arr.length;
document.write(LAS(arr, n));
</script>
|
Output:
6
Time Complexity: O(N)
Auxiliary Space: O(1)
Last Updated :
21 Dec, 2022
Like Article
Save Article
Share your thoughts in the comments
Please Login to comment...