【Leetcode】933. 最近的请求次数

QUESTION

easy

题目描述

写一个 RecentCounter 类来计算最近的请求。
它只有一个方法:ping(int t),其中 t 代表以毫秒为单位的某个时间。
返回从 3000 毫秒前到现在的 ping 数。
任何处于 [t - 3000, t] 时间范围之内的 ping 都将会被计算在内,包括当前(指 t 时刻)的 ping
保证每次对 ping 的调用都使用比之前更大的 t

示例:

输入:inputs = ["RecentCounter","ping","ping","ping","ping"], inputs = [[],[1],[100],[3001],[3002]]
输出:[null,1,2,3,3]

说明

  • 每个测试用例最多调用 10000ping
  • 每个测试用例会使用严格递增的 t 值来调用 ping
  • 每次调用 ping 都有 1 <= t <= 10^9

SOLUTION

此题的关键是读懂题目,如果理解了题目就很好写了。

简单解释一下,大概意思就是你每次 ping 都会伴随一个时间点 t,而你的任务就是,ping 的同时你要返回 [t - 3000, t] 这个时间段 ping 的次数,注意是闭区间。

方法一(二分搜索)

这个问题的关键就在于给定的 ping 的时间 t 是严格递增的(很真实),而它需要你返回一个区间内的总 ping 数,那么只要我们使用数组来储存每个 ping 的时间点,然后找到第一个不小于 t -3000 的数组下标 index,通过 size() - index 就能求出我们想要的答案。为了缩短查找时间我们采用二分搜索。

class RecentCounter {
public:
    RecentCounter() {}
    int ping(int t) {
        time.push_back(t);
        int l = binary_search_lower_bound(t - 3000);
        return time.size() - l;
    }
private:
    vector<int> time;
    int binary_search_lower_bound(int target){
        int r = time.size() - 1;
        int l = 0;
        while(l <= r){
            int mid = l + (r - l) / 2;
            if(time[mid] < target) l = mid + 1;
            else r = mid - 1;
        }
        return r + 1;
    }
};

方法二(二分搜索改进)

仔细思考题目可以发现,由于范围是固定的 3000,所以如果我们改为每次去查找最后一个小于 t - 3000 数组下标 index,同时用一个变量保存以用于下一次的二分搜索的左起始点,就能缩短一些查找时间。

class RecentCounter {
public:
    RecentCounter() {
        index = 0;
    }
    int ping(int t) {
        time.push_back(t);
        int res = binary_search(t - 3000);
        return time.size() - res - 1;
    }
private:
    vector<int> time;
    int index;
    int binary_search(int target){
        int r = time.size() - 1;
        int l = index;
        while(l <= r){
            int mid = l + (r - l) / 2;
            if(time[mid] < target) l = mid + 1;
            else r = mid - 1;
        }
        return r; //注意这里不是 r + 1
    }
};

方法三(队列)

既然 t 严格递增,而查找的范围又是固定的 3000, 那我每次记录的同时,都把用不着的删掉不就行了吗,用一个队列实现

class RecentCounter {
public:
    RecentCounter() {}
    int ping(int t) {
        time.push(t);
        while(time.front() < t - 3000){
            time.pop();
        }
        return time.size();
    }
private:
    queue<int> time;
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值