您的位置:首页 > 其它

最长递增子序列

2014-12-21 18:22 169 查看
题目描述

给定一个长度为N的数组a0,a1,a2...,an-1,找出一个最长的单调递增子序列(注:递增的意思是对于任意的i<j,都满足ai<aj,此外子序列的意思是不要求连续,顺序不乱即可)。例如:给定一个长度为6的数组A{5, 6, 7, 1, 2, 8},则其最长的单调递增子序列为{5,6,7,8},长度为4。

思路一:采用DP思路,不过时间复杂度o(n^2)

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/*如果要求a[i]的最长递增子序列
需要遍历0-i之间,找到是否可以增加a[i]
其中rec[]数组记录0-i在任何一个位置的最长递增序列的长度
如果可以增加a[i]到0-i中,则比较此时长度
如果比当前最大最大长度大,则更新rec[i]的值
依次往后,最终得到rec
的值则为最长递增序列的长度
*/

int LIS(int *a, int n)
{
int rec[255];
int i;
int j;

for (i=0; i<n; i++)
{
rec[i] = 1;
for (j=0; j<i; j++)
{
if (a[i]>a[j] && rec[i]<rec[j]+1) /*更新rec[i]的值*/
{
rec[i] = rec[j]+1;
}
}
}
return rec[n-1];
}
int main()
{
int a[] = {6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6};
printf("递增子序列长度为:%d\n", LIS(a, 11));

int b[] = {35, 36, 39, 3, 15, 27, 6, 42};
printf("递增子序列长度为:%d\n", LIS(b, 8));
return 0;
}
思路二:其实主要是对每次更新rec[i]的值要进行更新。如果能让它有序,则二分法查找可缩短时间复杂度

#include <stdio.h>
#include <stdlib.h>
/*说明:参考http://blog.csdn.net/beiyeqingteng/article/details/6954571
*/
int LIS(int *a, int n)
{
int rec[25]; /*记录递增子序列的最大值*/
int i;
int low;
int high;
int mid;
int len = 1;

rec[0] = a[0];
for (i=1; i<n; i++)
{
low = 0;
high = len;
while (low <= high)
{
mid = (low+high)/2;
if (rec[mid] < a[i])
{
low = mid+1;
}
else
{
high = mid-1;
}
}
rec[low] = a[i];/*将a[i]补充到序列后端*/
if (low > len)
{
len++;
}
}

return len+1;
}
int main()
{
int a[] = {6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6};
printf("递增子序列长度为:%d\n", LIS(a, 11));
int b[] = {35, 36, 39, 3, 15, 27, 6, 42};
printf("递增子序列长度为:%d\n", LIS(b, 8));
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: