算法应用题之今日头条的还该出多少道题?

题目描述

头条的2017校招开始了!为了这次校招,我们组织了一个规模宏大的出题团队。每个出题人都出了一些有趣的题目,而我们现在想把这些题目组合成若干场考试出来。在选题之前,我们对题目进行了盲审,并定出了每道题的难度系数。一场考试包含3道开放性题目,假设他们的难度从小到大分别为a, b, c,我们希望这3道题能满足下列条件:
 a<= b<= c
 b - a<= 10
 c - b<= 10
所有出题人一共出了n道开放性题目。现在我们想把这n道题分布到若干场考试中(1场或多场,每道题都必须使用且只能用一次),然而由于上述条件的限制,可能有一些考试没法凑够3道题,因此出题人就需要多出一些适当难度的题目来让每场考试都达到要求。然而我们出题已经出得很累了,你能计算出我们最少还需要再出几道题吗?

思路

方法 1

直接暴力求解,定义4个数组,第一个数组用于接受数据,剩下三个数组用于保存遍历的值。首先对保存数据的数组进行排序。然后进行整体遍历,遍历方式为
第一个值为从数据中取的值我们放到数组1,第二个值为与它差值在10之内的值,如果找到第二个值我们把它放到数组2,第三个值为与第二个值相差10的值如果找到我们放到数组3。每次再找下一个数组时,只要把新值找到了,就要把旧值在原数据删除。就这样把一个数一直遍历到原数据的数组尾部。
所以这个方法时间复杂度在O(N^2)

方法2

不用借助辅助空间,直接对保存数据的数组进行一次快排。因为排序后数据都是有序的,所以我们以区间的方式遍历。如果前后俩个元素差值在10以内我们就把它划分为我们的区间中。
就这样遍历只要前后俩个数据差值超过10,对已经划分好的区间大小模3,我们就可以得到在这个区间内应出的卷子数,因为区间中的元素都是有序的,又因为3个为1组,所以整体模3取余数为还应出的卷子数。然后继续遍历直到遍历到数组结尾即可。
这个方法复杂度 O(nlogn)

代码

方法1
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
int main()
{
    int nums;
    cin >> nums;
    vector<int> v;
    vector<int> temp1(0);
    vector<int> temp2(0);
    vector<int> temp3(0);
    int temp;
    v.resize(nums);
    int ret = 0;
    for(size_t idx=0;idx<nums;++idx)
    {
         cin>>temp;
         v[idx]=temp;
    }
    std::sort(v.begin(), v.end());
    vector<int>::iterator it;
    vector<int>::iterator del;
    if (nums == 1)
    {
        cout << 2 << endl;
        return 0;
    }
    if (nums == 2)
    {
        cout << 1 << endl;
        return 0;
    }
    while (it != v.end())
    {
        it = v.begin();
        int key = *it;
        del = it;
        temp1.push_back(key);
        while ((++it != v.end()) && (*it - key>10));
        if (it != v.end())
        {
            temp2.push_back(*it);
            v.erase(del);
            --it;
            del = it;
            key = *it;
            while ((++it != v.end()) && (*it - key>10));
            if (it != v.end())
            {
                temp3.push_back(*it);
                v.erase(del);
                --it;
                v.erase(it);
            }
            else{
                v.erase(del);
            }
        }
        else{
            v.erase(del);
        }
        it = v.begin();
    }
    ret = (temp1.size() - temp2.size()) * 2 + (temp2.size() - temp3.size());
    cout << ret << endl;
    return 0;
}

方法2

#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
int main(){
    int N;
    cin >> N;

    vector<int> num(N, 0);
    for (int i = 0; i < N; ++i){
        cin >> num[i];
    }

    sort(num.begin(), num.end());
    int res = 0;
    int count = 1;
    for (int i = 1; i < N; i++){
        if (num[i] - num[i - 1] <= 10)
            count++;
        else{
            if (count % 3 != 0)
                res += (3 - (count % 3));
            count = 1;
        }
    }

    if (count % 3 != 0)
        res += (3 - (count % 3));

    cout << res << endl;

    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值