Longest alternating subsequence

• Difficulty Level : Medium
• Last Updated : 28 Aug, 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++ program to find longest alternating``// subsequence in an array``#include``using` `namespace` `std;`` ` `// Function to return max of two numbers``int` `max(``int` `a, ``int` `b)``{``    ``return` `(a > b) ? a : b;``}`` ` `// Function to return longest alternating``// subsequence length``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[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 code``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;``}` `// This code is contributed by shivanisinghss2110`

C

 `// C program to find longest alternating subsequence in``// an array``#include ``#include ` `// function to return max of two numbers``int` `max(``int` `a, ``int` `b) {  ``return` `(a > b) ? a : b; }` `// Function to return longest alternating subsequence length``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[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

 `// Java program to find longest``// alternating subsequence in an array``import` `java.io.*;` `class` `GFG {` `// Function to return longest``// alternating subsequence length``static` `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

 `# Python3 program to find longest``# alternating subsequence in an array` `# Function to return max of two numbers``def` `Max``(a, b):``    ` `    ``if` `a > b:``        ``return` `a``    ``else``:``        ``return` `b` `# Function to return longest alternating``# subsequence length``def` `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 Code``arr ``=` `[ ``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#

 `// C# program to find longest``// alternating subsequence``// in an array``using` `System;` `class` `GFG``{` `// Function to return longest``// alternating subsequence length``static` `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 Code``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));``}``}` `// This code is contributed by anuj_67.`

PHP

 ` ``\$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.``?>`

Javascript

 ``

Output:

`Length of Longest alternating subsequence is 6`

Time Complexity: O(n2
Auxiliary Space: O(n), since n extra space has been taken.

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++

 `// C++ program for above approach``#include ``using` `namespace` `std;` `// Function for finding``// longest alternating``// subsequence``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` `max(inc, dec);``}` `// Driver Code``int` `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

 `// Java Program for above approach``public` `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

 `# Python3 program for above approach``def` `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 Code``if` `__name__ ``=``=` `"__main__"``:``    ``arr ``=` `[``10``, ``22``, ``9``, ``33``, ``49``, ``50``, ``31``, ``60``]``    ``n ``=` `len``(arr)``    ` `    ``# Function Call``    ``print``(LAS(arr, n))`

C#

 `// C# program for above approach``using` `System;` `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 ``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`

Javascript

 ``

Output:

`6`

Time Complexity: O(n)
Auxiliary Space: O(1)