先来看一个问题:给出一个数组,求这个数组的最大子序列。
这个问题很基础很常见,我们最简单的方法就是先准备一个数组
例如:arr[7]={1,2,5,8,4,3,2};
我们要求它的最长子序列,只要准备一个长度为7的数组和h[7]={0};
然后依次遍历arr将以arr中元素结尾的最长子序列放在h[7]中即可得到最长子序列的值,易得这是时间复杂度为O(n2);
再来看另一种做法,同样先准备一个数组h然后h中所存的元素先存arr[0],然后遍历,在和h中找到第一个比该元素大的,然后替换,若没有,则按顺序存入到h中,这样可以用二分查找,h中元素的意义为,当以该元素结尾的最长子序列为i+1;此时时间复杂度为
O(nlog(n));
这种算法是一个很复杂算法题的基础,就是当给定一系列二元组,(a1,b1),(a2,b2),(a3,b3),(a4,b4)...然后把这些二元组摞起来,
最多能摞多高,要求,ab都得从小到大,在其他地方,可能会看到俄国沙皇,一个代表权力,一个代表财富,思考一下这个问题因该怎么解决,很多地方来找到解法为O(n2)的算法,我们来看这一种解法。
********************
解法:
扫描二维码关注公众号,回复:
3007623 查看本文章
先把a排序,当a相等时,把b从大到小排列,然后就可以用最大子序列问题的方法来解决了,至于为什么要从大到小,因为要考虑a和b的权重,如果b很大,那么一定可以摞上去,所以要从大到小,这样就可以使用二分,所以时间复杂度就是O(nlong).
来一个两个数组最大子数组的问题,其本质思想就是第一个,我这里给出时间复杂度为O(n2)的,另一种,大家可以自己实现。
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
char* lcs(char* s1,char* s2)
{
int len1=strlen(s1);
int len2=strlen(s2);
int start,end,len;
end=len=0;
char c[len2];
for(int i=0;i<len1;i++)
{
for(int j=len2-1;j>=0;j--)
{
if(s1[i]==s2[j])
{
if(i==0||j==0)
{
c[j]=1;
}
else
{
c[j]=c[j-1]+1;
}
}
else
c[j]=0;
if(c[j]>len)
{
len=c[j];
end=j;
}
}
}
start=end-len+1;
char* p=malloc(len+1);
for(int i=start;i<=end;i++)
{
p[i-start]=s2[i];
}
p[len]='\0';
return p;
}
void main()
{
char str1[255],str2[255];
printf("input:\n");
gets(str1);
printf("input:\n");
gets(str2);
printf("%s\n",lcs(str1,str2));
}
用一个数组存放以str2中字符值结尾的最长子数组个数,然后遍历更新,最后输出位置和长度即可返回子数组。