📅  最后修改于: 2023-12-03 14:57:47.549000             🧑  作者: Mango
本题是一道经典的算法题,要求求解给定数列中最长的上升子序列的长度。可以使用多种算法实现,如动态规划算法、贪心算法等,在面试或算法竞赛中常常被提及。
给定一个长度为n的数列a1,a2,……,an,找到其中最长的上升子序列的长度。
例如,对于数列[10,9,2,5,3,4],最长的上升子序列为[2,5]或[2,3,4],长度为3。
本题可以使用动态规划算法实现,具体步骤如下:
定义状态:dp[i]表示以数列的第i个元素结尾的最长上升子序列的长度。
初始化状态:对于每个dp[i],均初始化为1,因为每个元素本身都可以构成上升子序列。
状态转移:对于第i个元素,枚举它之前的所有元素j(0<=j<i),如果dp[j]+1>dp[i](j处的最长子序列长度加1比i处的最长子序列长度还要大),则更新dp[i]为dp[j]+1。
最终答案:经过以上三个步骤,最长上升子序列的长度即为dp数组中的最大值。
def lengthOfLIS(nums):
n = len(nums)
if n == 0:
return 0
dp = [1] * n
for i in range(1, n):
for j in range(i):
if nums[j] < nums[i]:
dp[i] = max(dp[i], dp[j] + 1)
return max(dp)
以上为Python代码实现,时间复杂度为O(n^2)。
上述算法的时间复杂度较高,可以使用二分查找优化算法,具体步骤如下:
定义一个tails数组,每次遍历时,如果当前数字大于tails数组的最大值,直接将其拼接至tails数组末尾。
如果当前数字小于tails数组的最大值,使用二分查找在tails数组中找到最小的比该数字大的位置,并将该位置的值替换为当前数字。
最终tails数组的长度即为所求的最长上升子序列的长度。
def lengthOfLIS(nums):
n = len(nums)
tails = [0] * n
res = 0
for num in nums:
i, j = 0, res
while i < j:
mid = (i + j) // 2
if tails[mid] < num:
i = mid + 1
else:
j = mid
tails[i] = num
res = max(res, i + 1)
return res
以上为Python代码实现,时间复杂度为O(nlogn)。