求最长上升子序列长度以及具体的每一个最长子序列

求最长上升子序列长度以及具体的每一个最长子序列

使用复杂度为O(nlogn)的算法求解出最长上升子序列以及子序列长度为n时最小的数值为多少
用数组a存储,举例,a[2]=3表示长度为
2
的子序列的最小数是3
因为通过使用二分法查找数该插入的位置所以复杂度由O(n2)降为O(nlogn)
而后使用dfs(深搜)来求解具体的每一个最长子序列,用ans数组存储,数组开的较小,根据需要自行修改

!!!dfs需要注意不要重复搜索,重复进入,会导致重复搜索到然后重复输出!!!注意边界条件

结果展示:

求最长上升子序列长度以及具体的每一个最长子序列_第1张图片

代码部分:
#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;
}

你可能感兴趣的:(求最长上升子序列长度以及具体的每一个最长子序列)