最長上升子序列

最長上升子序列(Longest Increasing Subsequence,LIS)是一個在數列中尋找最長的元素序列的問題,其中每個元素都比其前一個元素大。例如,對於數列 [2, 10, 4, 7, 1, 5],最長上升子序列是 [1, 2, 4, 5],因為它是所有可能的上升子序列中最長的一個。

最長上升子序列問題可以用 Dynamic Programming 來解決,時間複雜度為 O(n^2),空間複雜度為 O(n)。以下是解決這個問題的一個簡單算法:

  1. 初始化一個長度為 n 的數組 dp,其中 dp[i] 表示數列中前 i 個元素的最長上升子序列的長度。
  2. 初始化一個長度為 n 的數組 lis,其中 lis[i] 表示數列中前 i 個元素的最長上升子序列的起始位置。
  3. 對於每個元素 nums[i],檢查它是否可以作為最長上升子序列的終點。如果 nums[i]nums[lis[dp[i-1]]] 大,那麼 dp[i] 就等於 dp[i-1] + 1,並且 lis[dp[i]] = i。否則,dp[i] 就等於 dp[lis[dp[i]]]
  4. 最後,最長上升子序列的長度就是 dp[n-1],而最長上升子序列本身則可以通過 lis[0..dp[n-1]-1] 來獲取。

以下是一個簡單的 Python 實現:

def lis(nums):
    n = len(nums)
    dp = [1] * n  # 初始化 dp[i] 為 1,表示以 nums[i] 結尾的最長上升子序列的長度為 1
    lis = [0] * n  # 初始化 lis[i] 為 0,表示以 nums[i] 結尾的最長上升子序列的起始位置為 0
    for i in range(n):
        for j in range(i):
            if nums[i] > nums[j] and dp[i] < dp[j] + 1:
                dp[i] = dp[j] + 1
                lis[i] = j
    return dp[-1], lis

# 示例
nums = [2, 10, 4, 7, 1, 5]
length, lis = lis(nums)
print(length)  # 輸出最長上升子序列的長度
print(lis)  # 輸出最長上升子序列的起始位置

這個算法的時間複雜度為 O(n^2),因為每一個 dp[i] 都需要檢查 O(n) 次。空間複雜度為 O(n),因為我們只需要額外的一個數組 dplis 來存儲狀態。

對於某些特定的數列,可能存在更高效的算法來解決最長上升子序列問題,例如對於隨機數列,可以使用二分查找來降低時間複雜度到 O(n log n)。但是,對於一般的數列,上述的動態規劃算法是最常用的解決方法。