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?
这是一道动态规划的经典问题。我们拿题中的例子来说事儿,题目要求只要返回LIS的长度即可。(我尽量用数字表示,感觉比较容易理解)。
0. 对于[10],LIS就是1。
1. 对于[10, 9], LIS还是1。因为9比10小所以无法构成上升序列。
2. 对于[10, 9, 2],LIS也还是1,原因同上,无法构成上升序列。
3. 对于[10, 9, 2, 5], 这个时候加入5,惊奇的发现可以有上升序列了,但问题是和谁构成上升序列。这个时候就需要一次比较之前的数字了。10和9都比5大所以只有2能和5构成上升序列。因此截止目前为止,由于数字5的加入,LIS为2([2, 5]).
4. 对于[10, 9, 2, 5, 3],加入3的时候,我们依旧依次比较之前的元素。10和9比3大,不够成IS,2和3构成IS,值为2,5比3大同样不构成上升序列。因此由于数字3的加入,造成了和数字2构成长度为2的上升序列。
5. 对于[10, 9, 2, 5, 3, 7],由于数字7的加入,这下就厉害了。10和9比7大不考虑,2和7构成长度为2的上升序列,5和7构成长度为2 + 1 = 3的上升序列(参见3),3和7构成长度为2 + 1 = 3的上升序列(参见4);
6. 对于[10, 9, 2, 5, 3, 7, 101],依次比较之前的元素,10和101构成长度为2的上升序列,9和101构成长度为2的上升序列,2和101构成长度为2的上升序列,5和101构成长度为3的上升序列,3和101构成长度为3的上升序列,7和101构成长度为4的上升序列(参考5,数字7和之前的数字可构成上升序列)。此时的LIS为4.
7. 对于[10, 9, 2, 5, 3, 7, 101, 18],加入数字18和上一步加入数字101情况是一样的,LIS为数字18和7构成的长度为4的上升序列,由于101比18大,因此它俩不构成上升序列。
走了一遍这个过程,我们发现,每当加入一个新的元素的时候,我们总是需要知道以之前的元素结尾的上升序列长度,并且是逐一比较取最大值。因此对于某一个元素nums[i],他的LIS为:max(1, dp[j] + 1) 此时j < i 且nums[j] < nums[i](等号要看对上升序列的定于)。
这个代码是O(n2)的解法,还有更优解今后再添加。
class Solution {
public:
int lengthOfLIS(vector<int>& nums) {
//10, 9, 2, 5, 3, 7, 101, 18
if (nums.size() == 0) return 0;
vector<int> dp(nums.size(), 1);
int len = 1;
for (int i = 0; i < nums.size(); i++) {
dp[i] = 1;
for (int j = 0; j < i; j++) {
if (nums[j] < nums[i] && dp[j] + 1 > dp[i]) {
dp[i] = dp[j] + 1;
}
len = max(dp[i], len);
}
}
return len;
}
};
参考资料: 动态规划:从新手到专家