📌  相关文章
📜  数组中最长子序列的长度,所有元素都为裸数字(1)

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

数组中最长子序列的长度

数组中的最长子序列是指一个数组中连续的一段序列,该序列中的元素可以按照任意顺序排列,但其在原始数组中的顺序必须保持不变,且所有元素均为裸数字(即没有单位或其他修饰)。

以下是一个简单的实现,使用一个动态规划数组 dp 来记录从每个元素开始的最长子序列长度。其中 dp[i] 表示以下标为 i 结尾的最长子序列长度。初始时,dp[i] 均为 1,即每个元素本身就是一个长度为 1 的子序列。然后遍历整个数组,对于每个位置 i,内部再次遍历前面的元素 j,如果 nums[i] 大于 nums[j],则可以将前面的最长子序列长度 dp[j] 加上 1,得到一个以 nums[i] 结尾的新的最长子序列长度。最后返回 dp 数组中的最大值即可。

def longest_subsequence(nums):
    n = len(nums)
    dp = [1] * n
    for i in range(1, n):
        for j in range(i):
            if nums[i] > nums[j]:
                dp[i] = max(dp[i], dp[j] + 1)
    return max(dp)

此算法的时间复杂度为 $O(n^2)$。我们还可以继续优化,使用一个辅助数组 tails 来记录目前为止已经处理过的元素中,最长的增序列。遍历整个数组时,对于每个位置 i,使用二分查找法将其插入到 tails 数组中,保持 tails 数组始终是一个有效的增序列,同时也是已处理元素中最长的增序列,此时的 tails 数组长度即为目前为止的最长子序列长度。

def longest_subsequence(nums):
    n = len(nums)
    tails = [0] * n
    size = 0
    for num in nums:
        i, j = 0, size
        while i < j:
            mid = i + (j - i) // 2
            if tails[mid] < num:
                i = mid + 1
            else:
                j = mid
        tails[i] = num
        size = max(size, i + 1)
    return size

此算法的时间复杂度为 $O(n \log n)$。