求最长上升子序列长度以及具体的每一个最长子序列
使用复杂度为O(nlogn)的算法求解出最长上升子序列以及子序列长度为n时最小的数值为多少
用数组a存储,举例,a[2]=3
表示长度为2的子序列的最小数是3
因为通过使用二分法查找数该插入的位置所以复杂度由O(n2)降为O(nlogn)
而后使用dfs(深搜)来求解具体的每一个最长子序列,用ans数组存储,数组开的较小,根据需要自行修改
!!!dfs需要注意不要重复搜索,重复进入,会导致重复搜索到然后重复输出!!!注意边界条件
结果展示:
代码部分:
#include<bits/stdc++.h>
using namespace std;
int a[100];
int d[100];
int len;
int ans[100];
int search(int x,int r){
int l=1;
while(l<=r){
int mid=(l+r)/2;
if(a[mid]==x){
return mid;
}else if(a[mid]>x){
r=mid-1;
}else{
l=mid+1;
}
}
return l;
}
void dfs(int start,int flag){
if(flag<=0){
for(int i=1;i<=len;i++){
cout<<ans[i]<<" ";
}
printf("\n");
return;
}
for(int i=start;i>=0;i--){//注意不用再dfs(i-1,flag),不选的情况已由for循环实现
if(d[i]>=a[flag]){
if(flag==len){
ans[flag]=d[i];
dfs(i-1,flag-1);
}else{
if(d[i]<ans[flag+1]){
ans[flag]=d[i];
dfs(i-1,flag-1);
}
}
}
}
}
int main(){
int n;
int flag=0;
cin>>n;
for(int i=0;i<n;i++){
cin>>d[i];
if(d[i]>a[flag]){
a[++flag]=d[i];
}else{
a[search(d[i],flag)]=d[i];
}
}
cout<<"最长上升子序列长度:"<<flag<<endl;
cout<<"最长上升子序列-表:"<<endl;
for(int i=1;i<=flag;i++){
cout<<a[i]<<" ";
}
cout<<endl;
len=flag;
cout<<"具体最长上升子序列:"<<endl;
dfs(n-1,flag);
return 0;
}