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 is4
. 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里面很经典的问题了,可是一开始想靠自己的想法把它推出来,结果还是有点难度。特别是在定义状态花费了太多时间,因为看到题目提示是O(N^2)的复杂度,所以以为状态会是dp[i][j]这种二维的形式。定势思维了,要改!
后来再想,dp问题的核心在于划分子问题上。想清楚1:能否划分为子问题 ;2:怎么从子问题推导出母问题(状态转移) 才是王道啊!
所以嘛,令dp[i]为以i为结尾的最长子序列。则dp[i]可以由前面怎么推出来呢?
对于所有的0<=j\ nums[j],那么可得dp[i] = dp[j] + 1;但是我们要求最长上升子序列,所以只需要维护所有j里面算出来dp[i]是最大的那个:dp[i] = max(dp[i], dp[j] + 1);**
1 | class Solution { |
参考了下Discuss大神的O(nLogN)的做法,不是特别能理解,所以在先做个摘录。
tails
is an array storing the smallest tail of all increasing subsequences with lengthi+1
intails[i]
.
For example, say we havenums = [4,5,6,3]
, then all the available increasing subsequences are:
1
2
3
4
5 > len = 1 : [4], [5], [6], [3] => tails[0] = 3
> len = 2 : [4, 5], [5, 6] => tails[1] = 5
> len = 3 : [4, 5, 6] => tails[2] = 6
>
>
>
We can easily prove that tails is a increasing array. Therefore it is possible to do a binary search in tails array to find the one needs update.
Each time we only do one of the two:
1
2
3
4 > (1) if x is larger than all tails, append it, increase the size by 1
> (2) if tails[i-1] < x <= tails[i], update tails[i]
>
>
>
Doing so will maintain the tails invariant. The the final answer is just the size.
参考大神的想法自己写出O(nLogN)的c++代码:
1 | // |