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(n2) complexity.
Follow up: Could you improve it to O(n log n) time complexity?
用DP的方法,每一个dp[i]代表从nums[0]到这个元素nums[i]的最长的inreasing subsequence的长度。O(N^2)的解法:
class Solution(object):
def lengthOfLIS(self, nums):
"""
:type nums: List[int]
:rtype: int
"""
if not nums:
return 0
n = len(nums)
dp = [1] * n for i in range(0, n):
for j in range(i+1, n):
if nums[j] > nums[i]:
dp[j] = max(dp[i] + 1, dp[j]) return max(dp)
解法二 O(N logN)
本题可以用一个dp list来维护LIS的solution。对于nums里面的数跑一个for loop。如果遇到dp = [],需要把当前的num填到dp list里面。如果发现num大于dp list的最后(也就是最大的那个数)就append上去。如果num在[dp[0], dp[-1]]区间内,用binary search找到num应该在的位置去替换相应的数。这么做的目的是,例如上图中用5替换了7,假如5后面有6,7两个数的话,就会取得一个更长的subsequence。注意mid和num比较时使用的是>还是>=。这回区间头是移动到mid+1还是mid。
def lengthOfLIS(self, nums):
"""
:type nums: List[int]
:rtype: int
"""
if not nums:
return 0
size = len(nums)
dp = []
for x in range(size):
if not dp or dp[-1] < nums[x]:
dp.append(nums[x])
low, high = 0, len(dp) - 1
while low < high:
mid = (low + high)/2
if dp[mid] < nums[x]:
low = mid + 1
else:
high = mid
dp[high] = nums[x] return len(dp)