2019校招深信服编程题(找出前10个访问网站的id发奖金)

题目描述:
输入一组数据,找出前10个输入的不同的数作为访问网站的用户id,发奖金。
输入第一个数n表示后面要输入多少个访问网站的id(可能重复)
输出第一个数表示得奖金的用户数,后面每一行输出得奖的用户id,注意是按照访问网站的时间顺序输出。

#include
#include
#include

using namespace std;

int main()
{
    set s_users;   //使用set的目的就是去重,只插入不重复的id。但是坏处是会被排序
    vector v_users;    //判断插入成功的,则存入vector,作为结果保存,可按时间顺序输出
    int n;
    cin >> n;   //输入后续要输入的访问次数
    int count = 0;  //记录统计的非重复id数,达到10个时退出循环,输出结果
    for (int i = 0; i < n; i++)
    {
        int id;
        cin >> id;
        pair::iterator, bool> pr = s_users.insert(id);  //最核心语句,根据insert返回值判断
        if (pr.second == true)
        {
            //说明此id第一次出现,加入set成功。则加入到vector
            v_users.push_back(id);
            count++;
            if (10 == count)
            {
                break;
            }
        }
    }

    cout << v_users.size() << endl;
    for (int id:v_users)
    {
        cout << id << endl;
    }
        return 0;
}

上面解法的重点在于会使用pair::iterator, bool> pr = s_users.insert(id);,然后就可以根据返回值判断是否插入成功。但是如果不知道这一句怎么办呢?
下面是一种稍显复杂,但是也挺有意思的解法。先用一个user结构体保存用户id以及访问网站的顺序index。先用set集合根据用户id来去重,但是得到的集合是按照用户id排序了的,而我们输出答案的时候要按照index排序输出。可以将set集合中的元素都复制添加到一个vector中,然后让vector根据index排序,再按照vector输出答案即可。
》在这种解法中还可以看到set自定义排序方式,使用STL的sort函数的自定义为vector排序方式。

#include
#include
#include
#include //使用全局的sort()函数会用到

using namespace std;
//使用struct和class的区别主要是,struct内成员默认是public,而class是默认private
struct user 
{
    int id; //用户id
    int index;  //访问网站的次序
    user(int &a, int &b):id(a),index(b){}
    //重载<操作符,试试能不能直接用于less的比较
    bool operator<(const user &a) const     //注意const不能少,否则编译报错
    {
        //return this->index < a.index; //用于vector根据index使用STL的sort进行排序
        return this->id < a.id; //用于set在定义时用于模板第二参数重载less根据id进行排序
    }
};
//仿函数,作为set定义时的参数,用于排序
class s_user_comp
{
public:
    bool operator()(const user &a, const user &b) 
    {
        //仿函数中必定会重载()操作符
        return a.id < b.id;
    }
};

//只定义一个函数,使用的时候直接将函数名作为sort()的第三参数,当做函数指针调用
bool v_users_comp_func(const user &a, const user &b)
{
    return a.index < b.index;
}
//使用仿函数来为sort()函数提供第三参数
class v_users_comp_obj
{
public:
    bool operator()(const user &a, const user &b)
    {
        //仿函数中必定会重载()操作符
        return a.index < b.index;
    }
};

int main()
{
    int n;
    cin >> n;
    //set s_users;   //使用外部的仿函数类来定义<
    //使用user类中重载的<来定义<,默认的less仿函数内部因为会用到<比较,此时能检测到<被重载了
    set s_users;      
    s_users.clear();
    for (int i = 0; i < n; i++)
    {
        int a;
        cin >> a;
        s_users.insert(user(a,i));  //用user(a,i)构造一个临时对象
        if (s_users.size() == 10)
        {
            break;  //检查的set中已有10个不同的id的用户,则退出循环
        }
    }

    int size = s_users.size();
    cout << size << endl;
    vector v_users;

    for (user u:s_users)
    {
        //遍历set,将元素都复制加入到vector
        v_users.push_back(u);
    }
    //使用函数指针进行排序,没问题,可以输出正确答案
    //sort(v_users.begin(), v_users.end(), v_users_comp_func);  
    //使用仿函数传入临时对象进行排序,没问题,可以输出正确答案
    sort(v_users.begin(), v_users.end(), v_users_comp_obj());   
    //使用user类内部重载的<号进行排序,没问题,可以输出正确答案
    //sort(v_users.begin(), v_users.end()); 
    for (user u : v_users)
    {
        //遍历vector,输出需要的用户id
        cout << u.id << endl;
    }

    return 0;
}

【总结】
1、对于set中自定义排序方式,可以有两种。
一是在要加入到set的元素user的类中重载<操作符,这样在set对象定义时只需简单的set s_users;即可;
二是在外部自定义仿函数(一个类)s_user_comp,重载()操作符,传入user引用作为重载函数的参数,使用时要将仿函数名传入set模板中替换掉默认的less仿函数,如set s_users;
2、对于给STL的sort函数自定义排序方式,可以有三种方式。
一是使用传入两个迭代器参数的sort函数,但是要在user类中重载<操作符;sort(v_users.begin(), v_users.end());
二是使用传入3个参数的sort函数,在外部自定义一个普通的比较函数,并传入函数名作为函数指针给sort的第三个参数;sort(v_users.begin(), v_users.end(), v_users_comp_func);
三是使用传入3个参数的sort函数,在外部自定义一个仿函数(类),并传入仿函数临时对象(类名()),作为sort的第三个参数。sort(v_users.begin(), v_users.end(), v_users_comp_obj());

你可能感兴趣的:(2019校招深信服编程题(找出前10个访问网站的id发奖金))