📜  最长交替子序列

📅  最后修改于: 2021-09-17 07:31:21             🧑  作者: Mango

如果序列 {x1, x2, .. xn} 的元素满足以下关系之一,则它是交替序列:

x1 < x2 > x3 < x4 > x5 < …. xn or 
  x1 > x2 < x3 > x4 < x5 > …. xn

例子 :

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.

这个问题是最长递增子序列问题的扩展,但需要更多的思考来找到最佳子结构属性。
我们将通过动态规划方法解决这个问题,让 A 给定长度为 n 的整数数组。我们定义了一个二维数组 las[n][2] ,这样 las[i][0] 包含最长的交替子序列,以索引 i 结束,最后一个元素大于它的前一个元素,而 las[i][1] 包含最长的交替子序列在索引 i 处结束并且最后一个元素小于它的前一个元素,那么我们之间有以下递推关系,

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]

第一个递推关系基于这样一个事实,如果我们在位置 i 并且这个元素必须大于它的前一个元素,那么为了这个序列(直到 i)更大,我们将尝试选择一个元素 j ( < i)这样 A[j] < A[i] 即 A[j] 可以成为 A[i] 的前一个元素并且 las[j][1] + 1 大于 las[i][0] 然后我们将更新拉斯[i][0]。
请记住,我们选择了 las[j][1] + 1 而不是 las[j][0] + 1 来满足替代属性,因为在 las[j][0] 中,最后一个元素比前一个元素大,而 A[i] 是大于 A[j] 这将破坏交替属性,如果我们更新。所以以上事实推导出第一个递推关系,对于第二递推关系也可以进行类似的论证。

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


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
        elif (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


输出:

Length of Longest alternating subsequence is 6

时间复杂度: O(n 2 )
辅助空间: O(n)

有效的解决方案:
在上述方法中,我们随时跟踪数组中每个元素的两个值(以索引 i 结尾的最长交替子序列的长度,并且最后一个元素小于或大于前一个元素)。为了优化空间,我们只需要为任何索引 i 处的元素存储两个变量。

inc = 迄今为止最长替代子序列的长度,当前值大于它的先前值。
dec = 迄今为止最长替代子序列的长度,当前值小于它的先前值。
这种方法的棘手部分是更新这两个值。

“inc”应该增加,当且仅当替代序列中的最后一个元素小于它的前一个元素。
“dec”应该增加,当且仅当替代序列中的最后一个元素大于它的前一个元素。

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));
    }
}

蟒蛇3

# 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
        elif (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


输出:

6

时间复杂度: O(n)
辅助空间: O(1)

如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程学生竞争性编程现场课程