1. 最长递增子序列问题概述
最长递增子序列(Longest Increasing Subsequence, LIS)是动态规划领域的经典问题,也是算法面试中的高频考点。给定一个整数数组nums,我们需要找到其中最长的严格递增子序列的长度,并统计具有该长度的子序列的个数。
这个问题看似简单,但蕴含着动态规划思想的精髓。在实际应用中,LIS问题可以用于DNA序列比对、股票趋势分析、任务调度优化等多个领域。例如,在金融分析中,我们可以用LIS来识别一支股票价格的最长上涨周期;在生物信息学中,LIS算法可以帮助比较不同物种基因序列的相似性。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 基础解法:动态规划思路解析
2.1 状态定义与转移方程
对于基础的LIS问题(仅求长度),我们通常定义dp[i]表示以nums[i]结尾的最长递增子序列的长度。状态转移方程为:
code复制dp[i] = max(dp[j] + 1) for all j < i and nums[j] < nums[i]
这个方程的含义是:对于每个元素nums[i],我们检查它之前的所有元素nums[j],如果nums[j]小于nums[i],那么nums[i]可以接在nums[j]后面形成更长的子序列。
2.2 统计子序列数量的扩展
为了统计最长递增子序列的个数,我们需要在原有dp数组的基础上,增加一个count数组。count[i]表示以nums[i]结尾的最长递增子序列的个数。
当更新dp[i]时:
- 如果发现dp[j] + 1 > dp[i],说明找到了更长的子序列,此时需要重置count[i]为count[j]
- 如果dp[j] + 1 == dp[i],说明找到了相同长度的不同子序列,此时count[i] += count[j]
2.3 初始化与边界条件
初始时,每个元素本身就是一个长度为1的子序列,因此:
- dp数组初始化为1(每个元素至少可以形成长度为1的子序列)
- count数组初始化为1(每个元素至少有一种方式形成长度为1的子序列)
3. 完整算法实现与代码解析
3.1 Python实现代码
python复制def findNumberOfLIS(nums):
if not nums:
return 0
