合唱隊形算法問題記錄(大佬代碼是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;
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM