在一个随机序列中,寻找最长的递增子序列,这个子序列不要求连续。比如,给定序列[10, 9, 2, 5, 3, 7, 19, 18], 最长子序列为[2,3,7,19]或者[2,3,7,18], 因此结果为4。
第一种解法,是采用动态规划,复杂度为O^2. 使用一个辅助数组dp, 其中dp[i]保存源数组中以下标i结尾的最长递增子序列的个数.
n[0] = 10, dp[0] = 1
n[1] = 9 , dp[1] = 1
n[2] = 2 , dp[2] = 1
n[3] = 5 , dp[3] = 2 (2, 5)
n[4] = 3 , dp[4] = 2 (2, 3)
n[5] = 7 , dp[5] = 3 (2, 3, 7)
n[6] = 19, dp[6] = 4 (2, 3, 7, 19)
n[7] = 18, dp[7] = 4 (2, 3, 7, 18)
class Solution {
public:
int lengthOfLIS(vector<int>& nums) {
if(nums.empty()) return 0;
int ans = 1;
vector<int> dp(nums.size(),1);
for(int i = 1; i < nums.size(); i++) {
int maxC = 1;
for(int j = i-1; j >= 0; j--) {
if(nums[i] > nums[j]) {
maxC = max(maxC,dp[j]+1);
}
}
dp[i] = maxC;
ans = max(ans, maxC);
}
return ans;
}
};
第二种解法则用dp[i]保存长度为i+1的递增子序列中的最后一个元素。因为可能有多个长度为i+1的子序列,dp[i]保存最小的一个元素, 复杂度为n*log(n).
n[0] = 10, dp = [10]
n[1] = 9 , dp = [9]
n[2] = 2 , dp = [2]
n[3] = 5 , dp = [2,5]
n[4] = 3 , dp = [2,3]
n[5] = 7 , dp = [2,3,7]
n[6] = 19, dp = [2,3,7,19]
n[7] = 18, dp = [2,3,7,18]
class Solution {
public:
int lengthOfLIS(vector<int>& nums) {
if(nums.empty()) return 0;
vector<int> dp;
for(int i = 0; i < nums.size(); i++) {
if(dp.empty() || nums[i] > dp.back()) {
dp.push_back(nums[i]);
}
else {
auto it = lower_bound(dp.begin(), dp.end(), nums[i]);
*it = nums[i];
}
}
return dp.size();
}
};