题解 | #合唱队#

合唱队

https://www.nowcoder.com/practice/6d9d69e3898f45169a441632b325c7b4

#include <iostream>
#include <vector>
using namespace std;

//队形类
class Formation {
  private:
    //人数
    int N;

    //同学们的身高
    vector<int> classmatesHeights;

    //最长递增子序列长度
    vector<int> longestIncSubLen;

    //最长递减子序列长度
    vector<int> longestDecSubLen;

  public:
    //构造函数
    Formation(const int N) {

        //录入数据
        this->N = N;
        this->classmatesHeights.clear();
        for (int i = 0; i < N; i++) {
            int t = 0;
            cin >> t;
            this->classmatesHeights.push_back(t);
        }

        //数组置1
        this->longestIncSubLen.resize(this->N, 1);
        this->longestDecSubLen.resize(this->N, 1);
        return;
    }

    //析构函数
    ~Formation() {
        this->classmatesHeights.clear();
        this->longestDecSubLen.clear();
        this->longestIncSubLen.clear();
        return;
    }

    //在inc[i]处填充末端下标为i的最长递增子序列长度
    void IncLen(void) {

        // 进行判断前,考虑最坏情况,即整体为降序,每个最长递增子序列都只有一个元素
        // 但如果在范围内存在j<i,使得li[j]<li[i],则可以将下标为i的元素接到末端为li[j]的递增子序列的末端
        // 可得inc[i]=max{inc[i],inc[j]+1}

        // 从头开始遍历
        for (int i = 0; i < this->N; i++)

            //取比i小的j
            for (int j = 0; j < i; j++)

                //如果下标为j的同学身高小于下标为i的同学
                if (this->classmatesHeights[j] < this->classmatesHeights[i]) {
                    int a = this->longestIncSubLen[i];
                    int b = this->longestIncSubLen[j] + 1;
                    this->longestIncSubLen[i] = a < b ? b : a;
                }
        return;
    }

    //填充dec
    void decLen(void) {

        //从尾部开始遍历
        for (int i = this->N - 1; i >= 0; i--)

            //取比i大的j
            for (int j = this->N - 1; j > i; j--)

                //如果下标为j的同学身高小于下标为i的同学
                if (this->classmatesHeights[i] > this->classmatesHeights[j]) {
                    int a = this->longestDecSubLen[i];
                    int b = this->longestDecSubLen[j] + 1;
                    this->longestDecSubLen[i] = a < b ? b : a;
                }
        return;
    }

    //排成合唱队型需要出列的最少人数
    int numOfDequeue(void) {
        this->decLen();
        this->IncLen();

        //最长队列
        int maxLen = 0;
        for (int i = 0; i < this->N; i++) {
            int len = this->longestDecSubLen[i] + this->longestIncSubLen[i] - 1;
            maxLen = maxLen < len ? len : maxLen;
        }
        return this->N - maxLen;
    }
};

int main() {
    int N;
    while (cin >> N) { // 注意 while 处理多个 case
        cout << Formation(N).numOfDequeue() << endl;
    }
}
// 64 位输出请用 printf("%lld")

全部评论

相关推荐

评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务