题目描述
NNN位同学站成一排,音乐老师要请其中的(N−KN-KN−K)位同学出列,使得剩下的KKK位同学排成合唱队形。
合唱队形是指这样的一种队形:设K位同学从左到右依次编号为1,2,…,K1,2,…,K1,2,…,K,他们的身高分别为T1,T2,…,TKT_1,T_2,…,T_KT1,T2,…,TK, 则他们的身高满足T1<…Ti+1>…>TK(1≤i≤K)T_1<…<T_i>T_{i+1}>…>T_K(1 \le i \le K)T1<…<Ti>Ti+1>…>TK(1≤i≤K)。
你的任务是,已知所有N位同学的身高,计算最少需要几位同学出列,可以使得剩下的同学排成合唱队形。
输入格式
共二行。
第一行是一个整数N(2≤N≤100)N(2 \le N \le 100)N(2≤N≤100),表示同学的总数。
第二行有nnn个整数,用空格分隔,第iii个整数Ti(130≤Ti≤230)T_i(130 \le T_i \le 230)Ti(130≤Ti≤230)是第iii位同学的身高(厘米)。
输出格式
一个整数,最少需要几位同学出列。
输入输出样例
输入 #1
8
186 186 150 200 160 130 197 220
输出 #1
4
时间复杂度O(n^2)
要求出列的同学最少,就是要原来留下的同学最多,前半部分是个递增序列,后半部分是个递减序列,所以可以求处最长递增与递减序列,然后减1(重复计算了一次)
先分别开两个vector lis,lds,然后一个for 嵌套循环,用lis[i]来维护一个最长递增子序列的长度
lis[i]表示长度为i+1的序列,最长递增子序列的长度
同理,求递减子序列的时候,请从i从后往前,然后j从末尾递减到i,就是j一直是在i右边与i进行比较的,这样才能得出右侧的最长递减子序列
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main() {
int N;
cin >> N;
vector<int>heights;
int height;
for(int i = 1; i<=N;i++) {
cin>>height;
heights.push_back(height);
}
vector<int>lis = vector<int>(heights.size(),1);
vector<int>lds = vector<int>(heights.size(),1);
int size = heights.size();
for(int i = 0; i < size;i++) {
for(int j = 0;j < i;j++) {
if(heights[j] < heights[i]) {
lis[i] = max(lis[i],lis[j] +1);
}
}
}
for(int i = size-1;i>=0;i--) {
for(int j = size-1;j>i;j--) {
if(heights[j] < heights[i]) {
lds[i] = max(lds[i], lds[j]+1);
}
}
}
int ans = 1;
for(int i = 0; i< heights.size();i++) {
ans = max(ans,lds[i] + lis[i] -1);
}
cout<<N-ans<<endl;
}