华为笔试:合唱队

题目描述
计算最少出列多少位同学,使得剩下的同学排成合唱队形

说明:

N位同学站成一排,音乐老师要请其中的(N-K)位同学出列,使得剩下的K位同学排成合唱队形。
合唱队形是指这样的一种队形:设K位同学从左到右依次编号为1,2…,K,他们的身高分别为T1,T2,…,TK, 则他们的身高满足存在i(1<=i<=K)使得T1…>TK。
你的任务是,已知所有N位同学的身高,计算最少需要几位同学出列,可以使得剩下的同学排成合唱队形。

输入描述:
整数N

输出描述:
最少需要几位同学出列

示例1
输入
8
186 186 150 200 160 130 197 200
输出
4
解题思路:
首先计算每个数在最大递增子串中的位置

186 186 150 200 160 130 197 200 quene

1 1 1 2 2 1 3 4 递增计数

然后计算每个数在反向最大递减子串中的位置—>计算反向后每个数在最大递增子串中的位置

200 197 130 160 200 150 186 186 反向quene

1 1 1 2 3 2 3 3 递减计数

然后将每个数的递增计数和递减计数相加

186 186 150 200 160 130 197 200 quene

1 1 1 2 2 1 3 4 递增计数

3 3 2 3 2 1 1 1 递减计数

4 4 3 5 4 2 4 5 每个数在所在队列的人数+1(自己在递增和递减中被重复计算)

如160这个数

在递增队列中有2个人数

150 160

在递减队列中有2个人数

160 130

那么160所在队列中就有3个人

150 160 130

每个数的所在队列人数表达就是这个意思

总人数 - 该数所在队列人数 = 需要出队的人数
完整代码:

#include
#include
#include
using namespace std;
void CallNum(vector<int>num,vector<int>&inc)
{
    for(unsigned i=1;i<num.size();i++)
        for(int j=i-1;j>=0;j--)
        {
            if(num[j]<num[i]&&inc[j]+1>inc[i])
                inc[i]=inc[j]+1;
        }
}
int main()
{
    int N;
    while(cin>>N)
    {
        vector<int>num;
        vector<int>inc(N,1);
        vector<int>dec(N,1);
        vector<int>total;
        int n;
        for(int i=0;i<N;i++)
        {
            cin>>n;
            num.push_back(n);
        }
        CallNum(num,inc);
        reverse(num.begin(),num.end());
        CallNum(num,dec);
        reverse(dec.begin(),dec.end());
        int max=0;
        for(int j=0;j<N;j++)
        {
            total.push_back(inc[j]+dec[j]);
            if(total[j]>max)
                max=total[j];
        }
        cout<<N-max+1<<endl;
    }
    return 0;
}

牛客网编译器环境运行结果:
华为笔试:合唱队_第1张图片

你可能感兴趣的:(编程练习)