Input
10 9 2 5 3 7 101 18
Output
4 (因為2,3,7,101是最長的遞增子序列)
解題思路
該問題滿足最優(yōu)子結(jié)構(gòu)性質(zhì),因此可以使用動態(tài)規(guī)劃求解。
定義如下符號:
-
表示問題序列的總長度。
-
表示下標從1到i的一個序列,特別地,
表示下標從1開始,長度為n的一個序列,也就是問題的輸入。
-
表示
中的第
個元素。
由于問題的最優(yōu)解必然對應(yīng)某個子序列,而這個子序列又必然由某個結(jié)尾,因此,由所有
結(jié)尾的最長遞增序列的長度,構(gòu)成了問題的解空間。因此,再引入符號L,來描述問題的解空間:
-
表示以
結(jié)尾的最長遞增子序列的長度。
顯然,為該遞增子序列的最大值,
就是問題的最優(yōu)解。
求解,就要得到所有的
。求解
這一問題,包含了求解從
到
的所有子問題,從而滿足最優(yōu)子結(jié)構(gòu)性質(zhì)。
遞歸方程如下:
轉(zhuǎn)換成代碼,思路就是遍歷所有,選擇滿足
的最大的
,則
,如果
比所有
都要小,則
。
完整代碼
Leetcode上面有這個問題,可以上去檢驗一下:
class Solution {
public:
int max(const int &a, const int &b)
{
return a>b?a:b;
}
int lengthOfLIS(vector<int> &nums)
{
int n = nums.size();
int res = 1;
if(nums.size() == 0) return 0;
int *l = new int[n];
l[0] = 1;
for(int i = 1; i < n; i++) //填充L
{
int maxval = 1;
for(int j = 0; j < i; j++) //遍歷所有的A
{
if(nums[i] > nums[j])
{
maxval = max(maxval, l[j]+1);
}
l[i] = maxval;
}
}
for(int i = 0; i < n; i++)
{
if(l[i]>res)
{
res = l[i];
}
}
return res;
}
};