题解 | #合唱队#
合唱队
https://www.nowcoder.com/practice/6d9d69e3898f45169a441632b325c7b4
#include <iostream> #include <vector> using namespace std; int main() { int n,maxlen=0; cin>>n; vector<int> v(n),dp1(n,1),dp2(n,1); for(int i=0;i<n;++i)cin>>v[i]; for(int i=1;i<n;++i){ for(int j=0;j<i;++j){// 记录左侧 if(v[j]<v[i]){ dp1[i]=max(dp1[i],dp1[j]+1); } } } for(int i=n-2;i>=0;--i){ dp2[i]=1; for(int j=n-1;j>i;--j){// 记录右侧 if(v[j]<v[i]){ dp2[i]=max(dp2[i],dp2[j]+1); } } } for(int i=0;i<n;i++){ if(dp1[i]+dp2[i]-1>maxlen)maxlen=dp1[i]+dp2[i]-1; } cout<<n-maxlen<<endl; }
思路:
将问题抽象为:寻找队列中”最大“的中间数,每一个数可以看作一个单个"合唱队"。对每一个数对应两个参数:左边递减的数、右边递减的数。在依次遍历完成后,寻找左右参数之和最大的数(根据自己实际代码要注意是否需要减1),即为合唱队最多人数。
算法:动态规划(时间复杂度
)
以我个人看来,这道题无疑是动态规划的入门最佳题。从问题拆分到历史数据记录都能有所体现,而且在历史数据记录的问题上可以从for循环的方向选择中有所体现。换个说法就是从0向n-1遍历(++i)和从n-1向0遍历(--i)是不同的记录过程。具体的就多做两道题或者看看这道题解(思路很像的)合并表记录
春节怠慢了,后续会继续努力寻找有意思的题目分享