最长递增子序列和-题解
一、题目链接
https://www.nowcoder.com/practice/dcb97b18715141599b64dbdb8cdea3bd?tpId=40&rp=1&ru=%2Fta%2Fkaoyan&qru=%2Fta%2Fkaoyan%2Fquestion-ranking&tab=answerKey
二、题目分析
算法思路:动态规划
算法分析:
用dp[i]记录遍历到a[i]时当前最长递增子序列和,采用双层循环,第一层遍历数组a,第二层更新dp[i](如果a[j]<a[i],判断是否要更新dp[i],也即是否把a[i]加入到以a[j]结尾的递增子序列中,dp[i]=max(dp[i],dp[j]+a[i])
代码:
1 #include<bits/stdc++.h> 2 using namespace std; 3 int n,a[1001],dp[1001]; 4 int main(){ 5 while(cin>>n){ 6 int ans=0; 7 for(int i=0;i<n;i++){ 8 cin>>a[i];dp[i]=a[i]; 9 } 10 for(int i=0;i<n;i++){ 11 for(int j=i-1;j>=0;j--){ 12 if(a[j]<a[i]) dp[i]=max(dp[i],dp[j]+a[i]); 13 } 14 ans=max(ans,dp[i]); 15 } 16 cout<<ans<<endl; 17 } 18 }
若问最长上升子序列的长度,代码如下:
注:只需修改dp的值,dp[i]值从【最长递增子序列】和变成【最长递增子序列】长度
1 #include<bits/stdc++.h> 2 using namespace std; 3 int n,a[1001],dp[1001]; 4 int main(){ 5 while(cin>>n){ 6 int ans=0; 7 for(int i=0;i<n;i++){ 8 cin>>a[i];dp[i]=1;//修改这 9 } 10 for(int i=0;i<n;i++){ 11 for(int j=i-1;j>=0;j--){ 12 if(a[j]<a[i]) dp[i]=max(dp[i],dp[j]+1);//修改这 13 } 14 ans=max(ans,dp[i]); 15 } 16 cout<<ans<<endl; 17 } 18 }
若问最长上升子序列的长度,并且要输出其中一个最长上升子序列,代码如下:
注:
1 #include<bits/stdc++.h> 2 #define N 100005 3 using namespace std; 4 int num[N],a[N],pre[N],pos[N]; 5 void print(int x){ 6 if(x==0) return; 7 print(pre[x]); 8 cout<<num[x]<<" "; 9 } 10 int main(){ 11 int n; 12 while(cin>>n){ 13 memset(a, 0x3f, sizeof(a)); 14 int len = 0; 15 for(int i=1; i<=n; ++i){ 16 cin>>num[i]; 17 int ll = lower_bound(a, a+len, num[i]) - a; 18 if(ll+1 > len) len = ll+1; 19 a[ll] = num[i];//第ll个位置新插入的数字num[i] 20 pos[ll] = i;//第ll个位置插入的是第i个数字 21 if(ll-1>=0) pre[i] = pos[ll-1];//当前插入的第i个数字的在递增序列中的前一个数字是第几个! 22 } 23 print(pre[pos[len-1]]); 24 cout<<(num[pos[len-1]])<<endl; 25 cout<<len<<endl; 26 } 27 return 0; 28 }