返回
一文读懂动态规划中的“最长上升子序列”及其时间复杂度优化
后端
2023-10-26 11:03:29
动态规划在计算机科学中是一种重要的算法范式,它能有效解决一系列优化问题。其中,“最长上升子序列”问题是动态规划的经典应用之一。本文将深入剖析该问题,并探索如何对其时间复杂度进行优化。
问题
最长上升子序列问题给定一个正整数序列,目标是找到其中长度最长的单调递增子序列。例如,对于序列 [3, 4, -1, 5, 8, 3, 6, 2, 7],最长上升子序列为 [3, 4, 5, 8, 6, 7]。
动态规划法
动态规划法解决最长上升子序列问题时,通常采用自底向上的方法:
- 初始化: 创建大小为 n 的数组 b,其中 b[i] 记录了以第 i 个元素为结尾的最长上升子序列的长度。
- 动态计算: 对于 i 从 1 到 n:
- 如果 a[i] > a[j](j < i),则 b[i] = max(b[i], b[j] + 1)
- 结果获取: 最长上升子序列的长度为 max(b[1], b[2], ..., b[n])
时间复杂度优化
最长上升子序列问题的基本动态规划算法时间复杂度为 O(n^2),其中 n 是序列的长度。通过使用二分查找技巧,我们可以将时间复杂度优化到 O(n log n):
- 初始化: 创建一个大小为 n 的数组 b,其中 b[i] 记录了以第 i 个元素为结尾的最长上升子序列的长度。将 b 初始化为 1。
- 动态计算: 对于 i 从 1 到 n:
- 如果 a[i] > a[j](j < i),则使用二分查找在 b[1:i-1] 中找到满足 b[l] < a[i] 且 b[l+1] >= a[i] 的 l 值。
- b[i] = max(b[i], l + 1)
- 结果获取: 最长上升子序列的长度为 max(b[1], b[2], ..., b[n])
代码示例
以下 Python 代码实现了最长上升子序列问题的优化动态规划算法:
def longest_increasing_subsequence(arr):
n = len(arr)
b = [1] * n
for i in range(1, n):
l = binary_search(b, 1, i-1, arr[i])
b[i] = max(b[i], l + 1)
return max(b)
def binary_search(arr, low, high, key):
while low <= high:
mid = (low + high) // 2
if arr[mid] < key:
low = mid + 1
else:
high = mid - 1
return low
结论
动态规划法是解决最长上升子序列问题的有效方法。通过采用二分查找技巧优化时间复杂度,该算法可以在更短的时间内高效找到序列中的最长上升子序列。掌握这些技巧将大大提升我们在解决类似优化问题时的效率。