Given an unsorted array of integers, find the length of longest increasing subsequence.
给定一个未排序的整数数组,返回该数组的最长递增子序列的长度。
Example:
Input: [10,9,2,5,3,7,101,18]
Output: 4
Explanation: The longest increasing subsequence is [2,3,7,101], therefore the length is 4.
Note:
- There may be more than one LIS combination, it is only necessary for you to return the length.
- Your algorithm should run in O(n2) complexity.
注意:
这里可能不止一种最长递增子序列额组合,你只需要返回其长度
你的算法的时间复杂度应该在O(n^2)
Follow up: Could you improve it to O(n log n) time complexity?
能否将算法时间复杂度降低到O(nlogn)?
动态规划法,创建一个dp数组,题目要求最长递增子序列,所以初始化dp数组中元素应设置较小,然后向大的方向更新。可知最差情况是nums中第 i 个元素的最长递增子序列长度为1,则初始化dp数组全为1。
考虑边界情况nums为空,则加入判断,当nums为空时,返回0
这道题的状态转移方程该如何写,我们不妨来考虑dp[ i ]所代表的含义,dp[ i ]可以代表以nums中第 i 个元素结尾的数组最长递增子序列长度,也可以代表nums中前 i 个元素其最长递增子序列长度,这是两个完全不同的概念,请不要混淆!如果dp[ i ]代表nums中前 i 个元素最长递增子序列长度,是求不出问题的解的,仔细考虑的话就会发现,dp[ i ]与dp[ j ](0= < j < i)之间没有办法建立状态转移方程。只有当dp[ i ]代表以nums中第 i 个元素结尾的最长递增子序列长度,才会得到dp[ i ]与dp[ j ]之间的关联(0= < j < i),即比较nums[ i ]与nums[ j ]的大小(0= < j < i),判断dp[ i ]是否需要进行加一操作,不断更新dp[ i ]的大小,直到 j 从 0 遍历到 i-1为止,所以状态转移方程:
从0到 i 开始搜索,两层嵌套循环,比较nums[ i ]与当前数nums[ j ]的大小,更新dp[ i ], dp[ i ] = max(dp[ i ],dp[ j ]+1),j从0到 i,切记dp[ i ]代表的是 【 以nums[ i ]为结尾 】的最长递增子序列长度 。
Solutions:
Python
class Solution:
def lengthOfLIS(self, nums: List[int]) -> int:
if len(nums) == 0:
return 0
dp = [1]*len(nums)
for i in range(1,len(nums)):
for j in range(0,i):
if nums[j]<nums[i]:
dp[i] = max(dp[i],dp[j]+1)
return max(dp)