Longest alternating subsequence - GeeksforGeeks

10 Mar, 2022
A sequence {x1, x2, .. xn} is 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
The whole arrays is of the form  x1 < x2 > x3 

Input: arr[] = {1, 4, 5}
Output: 2
All subsequences of length 2 are either of the form 
x1 < x2; or x1 > x2

Input: arr[] = {10, 22, 9, 33, 49, 50, 31, 60}
Output: 6
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.
This problem is an extension of longest increasing subsequence problem, but requires more thinking for finding optimal substructure property in this.We will solve this problem by dynamic Programming method, Let A is given array of length n of integers. We define a 2D array las[n][2] such that las[i][0] contains longest alternating subsequence ending at index i and last element is greater than its previous element and las[i][1] contains longest alternating subsequence ending at index i and last element is smaller than its previous element, then we have 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 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 alternate property because in las[j][0] 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 first recurrence relation, similar argument can be made for second recurrence relation also. 
C++
C
Java
Python3
C#
PHP
Javascript
// C++ program to find longest alternating// subsequence in an array#include<iostream>using namespace std;  // Function to return max of two numbersint max(int a, int b){    return (a > b) ? a : b;}  // Function to return longest alternating// subsequence lengthint zzis(int arr[], int n){         /*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 */    int las[n][2];      // Initialize all values from 1    for(int i = 0; i < n; i++)        las[i][0] = las[i][1] = 1;         // Initialize result    int res = 1;      // Compute values in bottom up manner    for(int i = 1; i < n; i++)    {                 // Consider all elements as        // previous of arr[i]        for(int j = 0; j < i; j++)        {                         // If arr[i] is greater, then            // check with las[j][1]            if (arr[j] < arr[i] &&                las[i][0] < las[j][1] + 1)                las[i][0] = las[j][1] + 1;              // If arr[i] is smaller, then            // check with las[j][0]            if(arr[j] > arr[i] &&               las[i][1] < las[j][0] + 1)                las[i][1] = las[j][0] + 1;        }          // Pick maximum of both values at index i        if (res < max(las[i][0], las[i][1]))            res = max(las[i][0], las[i][1]);    }    return res;}  // Driver codeint 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;} // This code is contributed by shivanisinghss2110
// C program to find longest alternating subsequence in// an array#include <stdio.h>#include <stdlib.h> // function to return max of two numbersint max(int a, int b) {  return (a > b) ? a : b; } // Function to return longest alternating subsequence lengthint zzis(int arr[], int n){    /*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   */    int las[n][2];     /* Initialize all values from 1  */    for (int i = 0; i < n; i++)        las[i][0] = las[i][1] = 1;     int res = 1; // Initialize result     /* Compute values in bottom up manner */    for (int i = 1; i < n; i++)    {        // Consider all elements as previous of arr[i]        for (int j = 0; j < i; j++)        {            // If arr[i] is greater, then check with las[j][1]            if (arr[j] < arr[i] && las[i][0] < las[j][1] + 1)                las[i][0] = las[j][1] + 1;             // If arr[i] is smaller, then check with las[j][0]            if( arr[j] > arr[i] && las[i][1] < las[j][0] + 1)                las[i][1] = las[j][0] + 1;        }         /* Pick maximum of both values at index i  */        if (res < max(las[i][0], las[i][1]))            res = max(las[i][0], las[i][1]);    }     return res;} /* Driver program */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 program to find longest// alternating subsequence in an arrayimport java.io.*; class GFG { // Function to return longest// alternating subsequence lengthstatic int zzis(int arr[], int n){    /*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 */    int las[][] = new int[n][2];     /* Initialize all values from 1 */    for (int i = 0; i < n; i++)        las[i][0] = las[i][1] = 1;     int res = 1; // Initialize result     /* Compute values in bottom up manner */    for (int i = 1; i < n; i++)    {        // Consider all elements as        // previous of arr[i]        for (int j = 0; j < i; j++)        {            // If arr[i] is greater, then            // check with las[j][1]            if (arr[j] < arr[i] &&                las[i][0] < las[j][1] + 1)                las[i][0] = las[j][1] + 1;             // If arr[i] is smaller, then            // check with las[j][0]            if( arr[j] > arr[i] &&              las[i][1] < las[j][0] + 1)                las[i][1] = las[j][0] + 1;        }         /* Pick maximum of both values at        index i */        if (res < Math.max(las[i][0], las[i][1]))            res = Math.max(las[i][0], las[i][1]);    }     return res;} /* Driver program */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));}}// This code is contributed by Prerna Saini
# Python3 program to find longest# alternating subsequence in an array # Function to return max of two numbersdef Max(a, b):         if a > b:        return a    else:        return b # Function to return longest alternating# subsequence lengthdef zzis(arr, n):     """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"""    las = [[0 for i in range(2)]              for j in range(n)]     # Initialize all values from 1    for i in range(n):        las[i][0], las[i][1] = 1, 1         # Initialize result    res = 1     # Compute values in bottom up manner    for i in range(1, n):             # Consider all elements as        # previous of arr[i]        for j in range(0, i):                 # If arr[i] is greater, then            # check with las[j][1]            if (arr[j] < arr[i] and             las[i][0] < las[j][1] + 1):                las[i][0] = las[j][1] + 1             # If arr[i] is smaller, then            # check with las[j][0]            if(arr[j] > arr[i] and            las[i][1] < las[j][0] + 1):                las[i][1] = las[j][0] + 1         # Pick maximum of both values at index i        if (res < max(las[i][0], las[i][1])):            res = max(las[i][0], las[i][1])     return res # Driver Codearr = [ 10, 22, 9, 33, 49, 50, 31, 60 ]n = len(arr) print("Length of Longest alternating subsequence is" ,      zzis(arr, n)) # This code is contributed by divyesh072019
// C# program to find longest// alternating subsequence// in an arrayusing System; class GFG{ // Function to return longest// alternating subsequence lengthstatic int zzis(int []arr, int n){    /*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 */    int [,]las = new int[n, 2];     /* Initialize all values from 1 */    for (int i = 0; i < n; i++)        las[i, 0] = las[i, 1] = 1;     // Initialize result    int res = 1;     /* Compute values in    bottom up manner */    for (int i = 1; i < n; i++)    {        // Consider all elements as        // previous of arr[i]        for (int j = 0; j < i; j++)        {            // If arr[i] is greater, then            // check with las[j][1]            if (arr[j] < arr[i] &&                las[i, 0] < las[j, 1] + 1)                las[i, 0] = las[j, 1] + 1;             // If arr[i] is smaller, then            // check with las[j][0]            if( arr[j] > arr[i] &&            las[i, 1] < las[j, 0] + 1)                las[i, 1] = las[j, 0] + 1;        }         /* Pick maximum of both        values at index i */        if (res < Math.Max(las[i, 0],                           las[i, 1]))            res = Math.Max(las[i, 0],                           las[i, 1]);    }     return res;} // Driver Codepublic 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));}} // This code is contributed by anuj_67.
<?php// PHP program to find longest// alternating subsequence in// an array // Function to return longest// alternating subsequence lengthfunction zzis($arr, $n){    /*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 */    $las = array(array());     /* Initialize all values from 1 */    for ( $i = 0; $i < $n; $i++)        $las[$i][0] = $las[$i][1] = 1;     $res = 1; // Initialize result     /* Compute values in    bottom up manner */    for ( $i = 1; $i < $n; $i++)    {        // Consider all elements        // as previous of arr[i]        for ($j = 0; $j < $i; $j++)        {            // If arr[i] is greater, then            // check with las[j][1]            if ($arr[$j] < $arr[$i] and                $las[$i][0] < $las[$j][1] + 1)               $las[$i][0] = $las[$j][1] + 1;             // If arr[i] is smaller, then            // check with las[j][0]            if($arr[$j] > $arr[$i] and               $las[$i][1] < $las[$j][0] + 1)                $las[$i][1] = $las[$j][0] + 1;        }         /* Pick maximum of both        values at index i */        if ($res < max($las[$i][0], $las[$i][1]))            $res = max($las[$i][0], $las[$i][1]);    }     return $res;} // Driver Code$arr = array(10, 22, 9, 33,             49, 50, 31, 60 );$n = count($arr);echo "Length of Longest alternating " .    "subsequence is ", zzis($arr, $n) ; // This code is contributed by anuj_67.?>
<script>    // Javascript program to find longest    // alternating subsequence in an array         // Function to return longest    // alternating subsequence length    function zzis(arr, n)    {        /*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 */        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;            }        }         /* Initialize all values from 1 */        for (let i = 0; i < n; i++)            las[i][0] = las[i][1] = 1;         let res = 1; // Initialize result         /* Compute values in bottom up manner */        for (let i = 1; i < n; i++)        {            // Consider all elements as            // previous of arr[i]            for (let j = 0; j < i; j++)            {                // If arr[i] is greater, then                // check with las[j][1]                if (arr[j] < arr[i] &&                    las[i][0] < las[j][1] + 1)                    las[i][0] = las[j][1] + 1;                 // If arr[i] is smaller, then                // check with las[j][0]                if( arr[j] > arr[i] &&                  las[i][1] < las[j][0] + 1)                    las[i][1] = las[j][0] + 1;            }             /* Pick maximum of both values at            index i */            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));         // This code is contributed by rameshtravel07.</script>
Output: 
Length of Longest alternating subsequence is 6
Time Complexity: O(n2) Auxiliary Space: O(n)
Efficient Solution:In the above approach, at any moment we are keeping track of two values (Length of the longest alternating subsequence ending at index i, and last element is smaller than or greater than previous element), for every element on array. To optimise 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.
C++
Java
Python3
C#
Javascript
// C++ program for above approach#include <bits/stdc++.h>using namespace std; // Function for finding// longest alternating// subsequenceint LAS(int arr[], int n){     // "inc" and "dec" initialized as 1    // as single element is still LAS    int inc = 1;    int dec = 1;     // Iterate from second element    for (int i = 1; i < n; i++)    {         if (arr[i] > arr[i - 1])        {             // "inc" changes iff "dec"            // changes            inc = dec + 1;        }         else if (arr[i] < arr[i - 1])        {             // "dec" changes iff "inc"            // changes            dec = inc + 1;        }    }     // Return the maximum length    return max(inc, dec);} // Driver Codeint main(){    int arr[] = { 10, 22, 9, 33, 49,                           50, 31, 60 };    int n = sizeof(arr) / sizeof(arr[0]);     // Function Call    cout << LAS(arr, n) << endl;    return 0;}
// Java Program for above approachpublic class GFG{         // Function for finding    // longest alternating    // subsequence    static int LAS(int[] arr, int n)    {                 // "inc" and "dec" initialized as 1,        // as single element is still LAS        int inc = 1;        int dec = 1;               // Iterate from second element        for (int i = 1; i < n; i++)        {                       if (arr[i] > arr[i - 1])            {                // "inc" changes iff "dec"                // changes                inc = dec + 1;            }            else if (arr[i] < arr[i - 1])            {                                 // "dec" changes iff "inc"                // changes                dec = inc + 1;            }        }               // Return the maximum length        return Math.max(inc, dec);    }       // Driver Code    public static void main(String[] args)    {        int[] arr = { 10, 22, 9, 33, 49,                               50, 31, 60 };        int n = arr.length;               // Function Call        System.out.println(LAS(arr, n));    }}
# Python3 program for above approachdef LAS(arr, n):       # "inc" and "dec" initialized as 1    # as single element is still LAS    inc = 1    dec = 1         # Iterate from second element    for i in range(1,n):               if (arr[i] > arr[i-1]):                       # "inc" changes iff "dec"            # changes            inc = dec + 1        else if (arr[i] < arr[i-1]):                       # "dec" changes iff "inc"            # changes            dec = inc + 1                 # Return the maximum length    return max(inc, dec) # Driver Codeif __name__ == "__main__":    arr = [10, 22, 9, 33, 49, 50, 31, 60]    n = len(arr)         # Function Call    print(LAS(arr, n))
// C# program for above approachusing System; class GFG{     // Function for finding// longest alternating// subsequencestatic int LAS(int[] arr, int n){         // "inc" and "dec" initialized as 1,    // as single element is still LAS    int inc = 1;    int dec = 1;        // Iterate from second element    for(int i = 1; i < n; i++)    {        if (arr[i] > arr[i - 1])        {                         // "inc" changes iff "dec"            // changes            inc = dec + 1;        }        else if (arr[i] < arr[i - 1])        {                         // "dec" changes iff "inc"            // changes            dec = inc + 1;        }    }        // Return the maximum length    return Math.Max(inc, dec);} // Driver code static void Main(){    int[] arr = { 10, 22, 9, 33,                  49, 50, 31, 60 };    int n = arr.Length;        // Function Call    Console.WriteLine(LAS(arr, n));}} // This code is contributed by divyeshrabadiya07
<script>    // Javascript program for above approach         // Function for finding    // longest alternating    // subsequence    function LAS(arr, n)    {         // "inc" and "dec" initialized as 1        // as single element is still LAS        let inc = 1;        let dec = 1;         // Iterate from second element        for (let i = 1; i < n; i++)        {             if (arr[i] > arr[i - 1])            {                 // "inc" changes iff "dec"                // changes                inc = dec + 1;            }             else if (arr[i] < arr[i - 1])            {                 // "dec" changes iff "inc"                // changes                dec = inc + 1;            }        }         // Return the maximum length        return Math.max(inc, dec);    }     let arr = [ 10, 22, 9, 33, 49, 50, 31, 60 ];    let n = arr.length;      // Function Call    document.write(LAS(arr, n));          // This code is contributed by mukesh07.</script>
Output:
6
Time Complexity: O(n) Auxiliary Space: O(1)
This article is contributed by Utkarsh Trivedi. Please write comments if you find anything incorrect, or you want to share more information about the topic discussed above.
vt_m
jigyansu
divyeshrabadiya07
shivanisinghss2110
divyesh072019
mukesh07
rameshtravel07
simranarora5sos
simmytarika5
Dynamic Programming
Dynamic Programming
Writing code in comment?
Please use ide.geeksforgeeks.org,
generate link and share the link here.
Bellman–Ford Algorithm | DP-23
Floyd Warshall Algorithm | DP-16
Subset Sum Problem | DP-25
Matrix Chain Multiplication | DP-8
Longest Palindromic Substring | Set 1
Travelling Salesman Problem | Set 1 (Naive and Dynamic Programming)
Edit Distance | DP-5
Sieve of Eratosthenes
Overlapping Subproblems Property in Dynamic Programming | DP-1
Maximum size square sub-matrix with all 1s