设给定的序列为num[n]
1.O(n^2)的求法
动态规划的方法
状态定义:设dp[i] 表示以num[i]结尾的最长单调递增子序列的长度
状态方程:dp[i] = max(dp[k] + 1 | num[k] < num[i], 0<=k<i), dp[i]初值为1
求法如下:
void MaxSubsequence(int n) //求最长递增子序列
{
int ma=0;
for(int i=0;i<n;i++)
{
dp[i]=1;
for(int j=0;j<i;j++)
if(num[j]<num[i] && dp[i]<dp[j]+1)
dp[i]=dp[j]+1;
if(ma<dp[i]) ma=dp[i];
}
printf("%d\n",ma);
}
空间换时间的方法 。
ind[i] :长度为i的单调递增子序列的最后一个元素的值
具体方法为:将num序列的每一个元素插入到ind数组中,插入位置通过二分查找获得,故复杂度为O(nlogn)。
ind的更新规则:插入数据比当前最后位置的数据大,直接将数据插入ind中;否则在ind中找到第一个比当前数据大 的位置(从左到右),替换当前位置的数据。 ind中的数据是有序的,所以可以用二分查找。
注意:ind数组中所存储的元素不一定就是符合条件的子序列,但所求的长度却是最大长度
eg:
num[]={2,3,5,1} 按照上述方法插入到ind数组中,结果为:1,3,5。
最长单调递增子序列长度为3,但1,3,5并不是符合要求的序列……
代码实现如下:
#include <iostream>
#include <string>
#include <algorithm>
#include <string.h>
const int INF = 0xffffff;
const int NUM = 10;
int ind[NUM];
int num[NUM];
int binary_search(int* array, int l, int r, int val)
{
int mid;
while(l <= r) {
mid = (l + r) / 2;
if(val > array[mid])
l = mid + 1;
else if(val < array[mid])
r = mid - 1;
else
return mid;
}
return l;
}
void LIS()
{
for(int i = 2; i < NUM; ++i)
ind[i] = INF;
ind[0] = -INF;
ind[1] = num[0];
int ind_len = 2;
int index;
for(int i = 1; i < NUM; ++i) {
index = binary_search(ind, 0, ind_len, num[i]);
ind[index] = num[i];
if(index == ind_len)
ind_len++;
}
std::cout << (ind[ind_len] == INF ? ind_len - 1 : ind_len) << std::endl;
}
int main()
{
for(int i = 0; i < NUM; ++i)
std::cin >> num[i];
LIS();
return 0;
}