Longest Increasing Subsequence
题目描述
Given an unsorted array of integers, find the length of longest increasing subsequence.
For example,
Given [10, 9, 2, 5, 3, 7, 101, 18]
,
The longest increasing subsequence is [2, 3, 7, 101]
, therefore the length is 4
. Note that there may be more than one LIS combination, it is only necessary for you to return the length.
Your algorithm should run in O(n^2)
complexity.
Follow up:
Could you improve it to O(n log n)
time complexity?
解题方法
DP O(n^2)
一开始我想用dp[i]来表示在[:i+1]里面的最长LIS, 但是这样很难就要像global, lobal一样建两个array, local用来表示以i为终点的LIS的长度,这样最后只要找出array中的最大值就可以了.
function
for k in range(0, i):
if nums[i] > nums[k] and dp[i] < dp[k] + 1:
dp[i] = dp[k] + 1
这种方法对于每个i都要遍历0~i-1, 所以需要O(n^2)
的复杂度
二分法
实际上,在对于i往前查找的过程中,只要比较nums[i]和之前LIS的最小结尾就可以, 比如
0 1 2 3 4 5 6 7
nums[]: 2 5 6 2 3 4 7 4
dp[]: 1 2 3 1 2 3 4 3
对于nums[6], 前面最大的LIS长度为3,并且有两个,但是我们只需要比较小的那个结尾,就可以确定 nums[6]是否可以接到后面。 如果不行的话,就再找小1个长度的LIS的最小结尾比较。
所以我们要建一个新的array, last_min, last_min[i]表示目前长度为i的LIS的最小结尾。
并且用一个variable curMax
记录目前最长的LIS, 这样便于比较。
而在查找这个i的过程可以使用二分法, 所以时间复杂度可以降到O(nlogn)
Solution
O(n^2)
class Solution(object):
def lengthOfLIS(self, nums):
"""
:type nums: List[int]
:rtype: int
"""
if not nums:
return 0
dp = [1 for i in range(len(nums))]
for i in range(1, len(nums)):
for j in range(0, i):
if nums[i] > nums[j] and dp[i] < dp[j] + 1:
dp[i] = dp[j] + 1
return max(dp)
O(nlogn)