给定一个列表{x_i},我想从每个元素开始找到longest increasing subsequence,以便起始元素包含在子序列中。
显而易见的方法是在每个元素上执行通常最长的增加子序列算法,给出O(n ^ 2 logn)。这可以被打败吗?
答案 0 :(得分:2)
您可以使用DP并将其降低到O(n ^ 2)。
让输入为x1,x2,...,xn
设f1,f2,...,fn是从第i个元素开始的最长增加序列的长度。将所有这些内容初始化为1。
现在,
for i = n-1, n-2, .... , 1:
for j = i,i+1,...,n:
if x[i]<x[j]:
fi=max(fi, fj+1)
如果除了长度之外还需要实际序列,请跟踪另一个变量g1,g2,...,gn,其中gi是下一个要遵循的元素。将gis初始化为NULL。
for i = n-1, n-2, .... , 1:
for j = i,i+1,...,n:
if x[i]<x[j]:
if fi<fj+1:
fi=fj+1
gi=j
一旦你有了gs,我将让你弄清楚如何从特定位置开始枚举序列。
答案 1 :(得分:1)
更高效的算法将依赖于每次迭代共享相同的数据结构,而不是每次都重新启动算法。一种方法是找到输入列表反向的最长递减子序列。这应该为您提供一个数据结构,使您可以对每个元素的前任进行持续访问,以及从该元素开始的子序列的长度。
对于每个起始元素:如果它处于最长的递减子序列中,请按照其前导到最后。如果不是,找到更大和更右边的元素,并拥有最多的前辈,并遵循该元素的前辈。
这将给出O(N ^ 2)的最坏情况时间复杂度,但至少还需要输出结果。
答案 2 :(得分:0)
int main(){
int arr[]={1,10,5,12,17,18,19};
int t[]={1,0,0,0,0,0,0};
int i,j;
vector<int>v[7];
v[0].push_back(1);
for(i =1;i<7;i++){
for(j =0;j<i;j++){
if(arr[j]<arr[i]){
if(t[j]>=t[i]){
t[i]=t[j]+1;
v[i].push_back(arr[j]);
}
}
}
if(i==j){
v[i].push_back(arr[i]);
}
}
for(i=0;i<7;i++){
for(j=0;j<v[i].size();j++){
cout<<v[i][j]<<" ";
}
cout<<endl;
}
return 0;
int arr[]={1,10,5,12,17,18,19};
int t[]={1,0,0,0,0,0,0};
int i,j;
vector<int>v[7];
v[0].push_back(1);
for(i =1;i<7;i++){
for(j =0;j<i;j++){
if(arr[j]<arr[i]){
if(t[j]>=t[i]){
t[i]=t[j]+1;
v[i].push_back(arr[j]);
}
}
}
if(i==j){
v[i].push_back(arr[i]);
}
}
for(i=0;i<7;i++){
for(j=0;j<v[i].size();j++){
cout<<v[i][j]<<" ";
}
cout<<endl;
}
return 0;
这是c ++代码,时间复杂度是N ^ 2.我会想出更优雅(使用map with pair)解决方案而不是这个。那将是nlogn命令。我没有在这里编写代码,因为这将取决于数据密度。如果数据密集,那么我将编写该方法,否则它将始终正常工作。