動態規劃最長子序列
動態規劃(Dynamic Programming)是一種解決最優化問題的算法設計策略,它將大問題分解為較小的、相似的子問題,並記錄這些子問題的答案以避免重複計算。最長子序列(Longest Increasing Subsequence,LIS)問題是一個經典的動態規劃問題。
給定一個數列,最長子序列問題旨在找出其中最長的子序列,該子序列的元素各不相同,並且按照遞增順序排列。例如,數列 [2, 3, 1, 2, 4]
的最長遞增子序列是 [1, 2, 2, 4]
,長度為4。
動態規劃解決最長子序列問題的算法如下:
- 初始化一個陣列
dp
,其長度與原數列相同,用來記錄每個元素的子序列的最長長度。 - 初始化
dp[0] = 1
,因為每個數列的開頭元素都構成一個長度為1的遞增子序列。 - 對於數列中的每個元素
i
(從1
到n-1
),找到所有長度為dp[i-1]
的遞增子序列的末尾元素。 - 如果數列中的元素
a[i]
大於這些末尾元素,那麼a[i]
開頭的子序列就是這些子序列的延長,因此dp[i] = dp[i-1] + 1
。 - 否則,
dp[i]
保持不變,因為a[i]
不能作為任何長度增加的遞增子序列的開頭。 - 最後,
dp
陣列中最大的元素就是最長遞增子序列的長度。
以下是一個簡單的Python實現:
def lis(arr):
n = len(arr)
dp = [1] * n # 初始化dp陣列
for i in range(1, n):
for j in range(i):
if arr[i] > arr[j]:
dp[i] = max(dp[i], dp[j] + 1)
return max(dp)
# 示例
arr = [2, 3, 1, 2, 4]
print(lis(arr)) # 輸出: 4
這個算法的時間複雜度為 O(n^2)
,空間複雜度為 O(n)
。存在更高效的算法,例如使用二分搜尋的版本,其時間複雜度為 O(n log n)
,但這是最基礎的動態規劃解法。