📜  计算递增的子序列数:O(NlogN)(1)

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

计算递增的子序列数:O(NlogN)

计算递增的子序列数是非常常见的问题,可以用动态规划或者二分查找来处理。其中动态规划的时间复杂度为O(N^2),本文将介绍一种时间复杂度为O(NlogN)的算法。

问题定义

给定一个长度为N的序列a,求其中递增的子序列个数。

算法思路

考虑维护一个递增的序列b,使得b中的最后一个元素最小。具体的,对于原序列中的每一个元素a[i],将其插入到b中的位置j,使得b[j-1] < a[i] <= b[j],如果不存在这样的位置,则将a[i]插入到b的末尾。此时,b[0]~b[j-1]构成的子序列长度均小于j,且以b[j]结尾。显然,b中元素个数即为递增子序列的个数。

算法实现

以下是该算法的Python实现:

def find_LIS(a):
    n = len(a)
    b = []
    for i in range(n):
        j = bisect_left(b, a[i])
        if j == len(b):
            b.append(a[i])
        else:
            b[j] = a[i]
    return len(b)

其中,bisect_left是Python内置的二分查找函数,其返回一个位置,即为a[i]需要插入到b中的位置。

算法分析

由于该算法在b中查找位置的操作采用了二分法,因此时间复杂度为O(NlogN)。而空间复杂度为O(N),即需要维护一个长度为N的b数组。

总结

本文介绍了一种时间复杂度为O(NlogN)的算法来计算递增的子序列数。该算法利用了二分查找的思想,可以在不使用动态规划的情况下求解。