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[i],表示以nums[i]结尾的最长递增子序列。遍历nums[i]之前的数,如果发现某个数小于nums[i],则更新dp[i], dp[i]=max(dp[i], dp[j]+1).返回dp数组的最大值。时间复杂度为O(n2).
class Solution {
public:
int lengthOfLIS(vector<int>& nums) {
int n = nums.size();
if (n == 0)
return 0;
vector<int>dp(n, 1);
int maxval=1;
for (int i = 1; i<n; ++i)
{
for (int j = i - 1; j >= 0; --j)
{
if (nums[j] < nums[i])
dp[i] = max(dp[i], dp[j] + 1);
}
if(dp[i]>maxval)
maxval=dp[i];
}
return maxval;
}
};
方法二:时间复杂度为O(nlogn).利用二分查找的思想。建立一个一维数组dp[i],开始遍历原数组,对每一个元素,用二分查找法找到第一个不小于它的的数字,如果这个数字不存在,则直接在后面添加该元素,如果存在,则将这个数字替换为当前遍历到的元素,最后返回dp的元素个数。注意:dp数组可能并不是一个真实的LIS.
int lengthOfLIS(vector<int>& nums) {
vector<int> res;
for(int i=0; i<nums.size(); i++) {
auto it = std::lower_bound(res.begin(), res.end(), nums[i]);
if(it==res.end()) res.push_back(nums[i]);
else *it = nums[i];
}
return res.size();
}