📅  最后修改于: 2023-12-03 15:28:05.063000             🧑  作者: Mango
计算递增的子序列数是非常常见的问题,可以用动态规划或者二分查找来处理。其中动态规划的时间复杂度为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)的算法来计算递增的子序列数。该算法利用了二分查找的思想,可以在不使用动态规划的情况下求解。