📜  O(n log n) 中最长的双调子序列(1)

📅  最后修改于: 2023-12-03 15:33:16.363000             🧑  作者: Mango

最长的双调子序列

介绍

在数学和计算机科学中,双调序列是指其元素首先单调递增,然后单调递减的序列。在一个长度为n的序列中,最长的双调子序列就是找到该序列中最长的一个双调子序列。这个问题在计算机科学中被称为最长的双调子序列问题。

这是一个经典的动态规划问题,时间复杂度为O(n log n)。

解决方案
算法
  1. 从左往右扫描,记录最长单调递增子序列的长度 lis[]。
  2. 从右往左扫描,记录最长单调递减子序列的长度 lds[]。
  3. 对于每个元素,计算 lis[i]+lds[i]-1(减一是因为 i 被算了两次),找到最大值。
代码
def longest_bitonic_subsequence(arr):
    n = len(arr)
    lis = [1] * n
    for i in range(1, n):
        for j in range(i):
            if arr[i] > arr[j] and lis[i] < lis[j] + 1:
                lis[i] = lis[j] + 1
    lds = [1] * n
    for i in range(n-2, -1, -1):
        for j in range(n-1, i, -1):
            if arr[i] > arr[j] and lds[i] < lds[j] + 1:
                lds[i] = lds[j] + 1
    max_len = 0
    for i in range(n):
        max_len = max(max_len, lis[i] + lds[i] - 1)
    return max_len
示例

输入: [1, 11, 2, 10, 4, 5, 2, 1]
输出: 6
解释: 可以找到长度为6的双调序列:[1, 2, 10, 4, 2, 1]。

总结

这个问题可以用动态规划算法解决,时间复杂度为O(n log n)。要解决这个问题,需要从左往右扫描,记录最长单调递增子序列的长度,然后从右往左扫描,记录最长单调递减子序列的长度。最后,对于每个元素,计算LIS[i]+LDS[i]-1,找到最大值。