第 444 场周赛——设计路由器

题目

设计路由器

题解

第二题就把我的上分梦击碎了,我的办法超时了差几个样例才能通过,需要对getCount进行优化。赛后看了灵神视频复盘。先入先出让我们首当其冲想到的就是通过队列存储,然后对于是否重复可以用set集合保存查询,但是set无法对三个参数进行哈希操作,需要我们提供一个哈希函数。getCount函数要求我们返回等于destination,timestamp在[startTime,endTime]之间的值,那我们可以将destination相同的分成一组,题目说如果超过限制将会把旧包丢出放入新包,那我们考虑对map中元素的删除,那我们可以多一维表示队头,然后startTime和endTime的位置用二分查找,最后中间的个数就是满足条件的数据包个数。

参考代码

//哈希函数
struct TupleHash {
    template<typename T>
    static void hash_combine(size_t& seed, const T& v) {
        seed ^= hash<T>{}(v) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
    }
    size_t operator()(const tuple<int, int, int>& t) const {
        auto& [a, b, c] = t;
        size_t seed = 0;
        hash_combine(seed, a);
        hash_combine(seed, b);
        hash_combine(seed, c);
        return seed;
    }
};

class Router {
    int memory_limit;
    queue<tuple<int, int, int>> packet_q;
    unordered_set<tuple<int, int, int>, TupleHash> packet_set;
    unordered_map<int, pair<vector<int>, int>> dest_to_timestamps;
public:
    Router(int memoryLimit) {
        memory_limit = memoryLimit;
    }
    
    bool addPacket(int source, int destination, int timestamp) {
        auto packet = make_tuple(source, destination, timestamp);
        if(!packet_set.insert(packet).second) return false;  //set的insert返回值是一个pair<iterator, bool>,first指向插入元素的迭代器,second表示是否插入成功。
        if(packet_q.size() == memory_limit) forwardPacket();
        packet_q.push(packet);
        dest_to_timestamps[destination].first.push_back(timestamp);
        return true;
    }
    
    vector<int> forwardPacket() {
        if(packet_q.empty()) return {};
        auto packet = packet_q.front();
        packet_q.pop();
        packet_set.erase(packet);
        auto [source, destination, timestamp] = packet;
        dest_to_timestamps[destination].second++;
        return {source, destination, timestamp};
    }
    
    int getCount(int destination, int startTime, int endTime) {
        auto& [timestamp, head] = dest_to_timestamps[destination];
        auto left = ranges::lower_bound(timestamp.begin() + head, timestamp.end(), startTime);
        auto right = ranges::upper_bound(timestamp.begin() + head, timestamp.end(), endTime);
        return right - left;
    }
};

/**
 * Your Router object will be instantiated and called as such:
 * Router* obj = new Router(memoryLimit);
 * bool param_1 = obj->addPacket(source,destination,timestamp);
 * vector<int> param_2 = obj->forwardPacket();
 * int param_3 = obj->getCount(destination,startTime,endTime);
 */
posted @ 2025-04-08 21:49  PZnwbh  阅读(11)  评论(0)    收藏  举报