• 合唱队形算法问题记录(大佬代码是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;
    }
  • 相关阅读:
    POJ 2104 K-th Number(区间第k大数)(平方切割,归并树,划分树)
    JAVA学习第四十一课 — 泛型的基本应用(一)
    (十九)组合模式详解
    计算机的组成 —— 主板
    计算机的组成 —— 主板
    查询电脑信息
    查询电脑信息
    计算机的组成 —— 显卡
    计算机的组成 —— 显卡
    云计算服务与基本术语、概念
  • 原文地址:https://www.cnblogs.com/gsp1004/p/11117822.html
Copyright © 2020-2023  润新知