合唱队形算法问题记录(大佬代码是C++,但是主要是看解题思路)

牛客网上的一个华为机试题,看完之后没思路,然后看了一个人的讲解,觉得思路很好,就在这里记录一下,题目如下:

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

说明:

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

我的附加说明:剩下的人你是不准去调整他们的位置的。这也是这个题的最难点,如果允许调整,那就so easy了(最大值只能有一个,其他值最多有2个,就是个简单的剔除过多数据的问题了。。。)

eg:

输入:

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 <iostream>
#include <vector>
#include <algorithm>
using namespace std;
 
void calIncSub(vector<int> quene, vector<int> &Num){
    for(int i=1;i<quene.size();i++)
        for(int j=i-1;j>=0;j--)
            if(quene[j]<quene[i] && Num[i]<Num[j]+1)  //找到前面比当前小的,且【能获得的最大子串计数】
                Num[i]=Num[j]+1;
}
 
int main(){
    int n;
    int h;
     
    while(cin>>n){
        vector<int> quene;
        vector<int> incNum(n,1);  //初始化为n个1
        vector<int> decNum(n,1); 
        vector<int> totalNum;
        for(int i=0;i<n;i++){
            cin >> h;
            quene.push_back(h);   
        }
        calIncSub(quene,incNum);    //找递增子串计数
        reverse(quene.begin(),quene.end()); //翻转,即找反向的子串计数
        calIncSub(quene,decNum);
        reverse(decNum.begin(),decNum.end());   //反向递增即正向递减
        int max=0;
        for(int i=0;i<n;i++){
            totalNum.push_back(incNum[i]+decNum[i]);
            if(totalNum[i]>max)
                max=totalNum[i];
        }
        cout << n-max+1 <<endl;
    }  
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/gsp1004/p/11117822.html
今日推荐