In an API rate-limiting system, each incoming requ...

創建於:2025年3月10日

使用 O1 回答 Chat01

問題

In an API rate-limiting system, each incoming request from a domain must be processed while adhering to certain request limits. There is a given array requests of size n, where requests[i] (0 ≤ i < n) represents the domain receiving a request at the th second.

The gateway allows at most 2 requests from a domain within a 5-second window, and at most 5 requests within a 30-second window.

Implement a function that determines whether each request can be processed. It should return "(status: 200, message: OK)" if the request is allowed, or "{status: 429, message: Too many requests)" if the request exceeds the rate limit.

The function getDomainRequestStatus takes the following input: string requests[n]: the list of domains making requests to the gateway

The function should return a list of strings representing the status of each request.

Example:

Suppose n = 7 and requests = ["www.xyz.com", "www.abc.com", "www.xyz.com", "www.pqr.com", "www.abc.com", "www.xyz.com", "www.xyz.com",]

Time

Request

Status of Request

0

www.xyz.com

Yes

{status: 200, message: OK)

1

www.abc.com

Yes

{status: 200, message: OK}

2

www.xyz.com

Yes

(status: 200, message: OK)

3

www.pqr.com

Yes

(status: 200, message: OK}

4

www.abc.com Yes

(status: 200, message: OK}

5

www.xyz.com

Yes

{status: 200, message: OK}

6

www.xyz.com

No -> 2 requests from "www.xyz.com" were accepted within 5 seconds.

{status: 429, message: Too many requests}

Hence the answer is ["{status: 200, message: OK)", "{status: 200, message: OK)", "(status: 200, message: OK)", "{status: 200, message: OK)", "{status: 200, message: OK)", "(status: 200, message: OK)", "(status: 429, message: Too many requests)"].

Constraints

1≤ns 104

1 length of requests[i] < 15

• requests[i] consists of lowercase English characters and dot ('.') characters.

▼Input Format For Custom Testing

The first line contains an integer, n, the number of elements in requests.

Each of the next n lines contains a string, requests[i].

▼Sample Case 0

Sample Input For Custom Testing

STDIN

FUNCTION

7

www.abc.com

→ requests =

requests[] size n = 7

["www.abc.com",

"www.hd.com",

"www.abc.com", "www.pqr.com", "www.abc.com", "www.pqr.com",

"www.pqr.com"]

www.hd.com

www.abc.com

www.pqr.com

www.abc.com

www.pqr.com

www.pqr.com

Sample Output

{status: 200, message: OK}

{status: 200, message: OK}

{status: 200, message: OK}

{status: 200, message: OK}

{status: 429, message: Too many requests}

{status: 200, message: OK}

{status: 429, message: Too many requests}

Explanation

• The fifth request is dropped because it exceeds the limit of 2 requests from "www.abc.com" within a 5-second window.

• Similarly, the last request is dropped as it exceeds the limit of 2 requests from "www.pqr.com" within a 5-second window.

▼ Sample Case 1

Sample Input For Custom Testing

STDIN

FUNCTION

www.hr.com

→ requests[] size n = 4

"www.hr.com"]

requests[] = ["www.hr.com", "www.hr.com", "www.hr.com",

4

www.hr.com

www.hr.com

www.hr.com

Sample Output

[status: 200, message: OK}

{status: 200, message: OK}

[status: 429, message: Too many requests)

[status: 429, message: Too many requests]

Explanation

The first two requests are allowed by the gateway. Requests from "www.hr.com" are blocked for the next 3 seconds due to exceeding the rate limit within the allowed time window.

Give C++ optimised code that runs for all possible test cases .

思考

Crafting request filters

I’m implementing getDomainRequestStatus in C++ to track domain requests. Each request must fall within specific recent limits to avoid "429" statuses. This approach ensures requests are within the acceptable range.

Streamlining request handling

I’m organizing incoming requests by keeping track of timestamps within sliding 30-second and 5-second windows using a deque for efficient O(log n) or O(1) time complexity.

Implementing a balanced approach

I’m detailing a balanced method to manage requests, aligning 30-second and 5-second sliding windows. This ensures precise outcomes for each domain to strategically block or allow requests.

Boundary management

I'm piecing together a structure to efficiently manage up to 10,000 requests. Using unordered_map with deque efficiently tracks and manages timestamps for each domain's requests within constraints.

Refining the approach

I’m focusing on efficiently managing requests by removing older ones, then monitoring the queue to ensure the most recent timestamps stay within the acceptable range for each sliding window.

Organizing request logs

I’m setting up dual deques for each domain: one for the past 30 seconds and another for the past 5 seconds. This method ensures precise adjustments and maintaining comprehensive data.

Tackling data

I’m closely examining request handling with optimized C++ code, ensuring O(n) complexity by managing older timestamps in two deques and monitoring the most recent timestamps for blocking decisions.

Reasoned about API rate-limiting logic for 56 seconds

回答

Below is an example of a concise, optimized C++ solution. The main idea is:

  1. Track requests per domain using two deques (or queues) for each domain:

    • A 5-second deque to quickly check the number of requests within the last 5 seconds.
    • A 30-second deque to quickly check the number of requests within the last 30 seconds.
  2. For each incoming request at time t=it = i:

    • Clean out entries in the 30-second deque older than t30t - 30.
      • If after cleaning, the deque size 5\geq 5, we reject the new request.
    • Clean out entries in the 5-second deque older than t4t - 4 (so that it covers the interval [t4t-4, tt]).
      • If after cleaning, the deque size 2\geq 2, we reject the new request.
    • If not rejected, we insert tt into both deques and accept the request.

This ensures O(1)O(1) amortized checks for each domain, since each request time is pushed and popped at most once from each deque. The solution easily handles up to 10410^4 requests.

cpp
#include <bits/stdc++.h> using namespace std; /* We define a function getDomainRequestStatus that takes: - n: number of requests - requests: vector of domain strings (each i-th request arrives at second i) Returns a vector of status messages corresponding to each request. Rate-limits: - At most 2 requests from the same domain in any rolling 5-second window - At most 5 requests from the same domain in any rolling 30-second window */ vector<string> getDomainRequestStatus(int n, const vector<string>& requests) { // We use an unordered_map (hash map) from domain -> pair of deques // first deque (fiveSec) to track timestamps within the last 5 seconds // second deque (thirtySec) to track timestamps within the last 30 seconds unordered_map<string, pair<deque<int>, deque<int>>> domainMap; domainMap.reserve(n); vector<string> result(n); for(int t = 0; t < n; t++){ const string& domain = requests[t]; // Retrieve (or create) the deques for this domain auto& dqPair = domainMap[domain]; auto& fiveSec = dqPair.first; // holds times in [t-4, t] auto& thirtySec = dqPair.second; // holds times in [t-29, t] // 1) Clean out old entries from the 30-second deque // Remove all timestamps <= t-30 while(!thirtySec.empty() && thirtySec.front() <= t - 30) { thirtySec.pop_front(); } // 2) After cleaning, if size >= 5 => block (429) if(thirtySec.size() >= 5) { result[t] = "{status: 429, message: Too many requests}"; continue; // do not record this request (do not push into deques) } // 3) Clean out old entries from the 5-second deque // Remove all timestamps < t-4 while(!fiveSec.empty() && fiveSec.front() < t - 4) { fiveSec.pop_front(); } // 4) After cleaning, if size >= 2 => block (429) if(fiveSec.size() >= 2) { result[t] = "{status: 429, message: Too many requests}"; continue; // do not push the new request into the deques } // If neither limit is exceeded, accept the request fiveSec.push_back(t); thirtySec.push_back(t); result[t] = "{status: 200, message: OK}"; } return result; } int main(){ ios::sync_with_stdio(false); cin.tie(nullptr); int n; cin >> n; // number of requests vector<string> requests(n); for(int i = 0; i < n; i++){ cin >> requests[i]; // read each domain request } // Compute the statuses vector<string> statuses = getDomainRequestStatus(n, requests); // Output the result for(const auto &s : statuses){ cout << s << "\n"; } return 0; }

Explanation of Key Steps

  1. unordered_map<string, pair<deque<int>, deque<int>>> domainMap;
    We keep for each domain two separate deques:

    • fiveSec tracks the timestamps of requests within the last 5 seconds.
    • thirtySec tracks the timestamps of requests within the last 30 seconds.
  2. Rolling Window Updates
    For a new request at time tt:

    • Remove from thirtySec any timestamps t30\leq t - 30. This ensures only requests in the last 30 seconds remain.
    • If after removal, thirtySec.size() 5\ge 5, block this request (rate limit reached).
    • Remove from fiveSec any timestamps <t4< t - 4. This ensures only requests in [t4,t][t-4, t] remain.
    • If after removal, fiveSec.size() 2\ge 2, block this request (rate limit reached).
    • If not blocked, we push the current time tt into both deques and mark the request as allowed.
  3. Complexities

    • Each request time tt is pushed and popped at most once from each deque, so all operations over nn requests are O(n)O(n) in total.
    • We use unordered_map to look up the deques for a given domain in average O(1)O(1) time.

This satisfies the constraints and ensures a clean, efficient rate-limiting mechanism for the 5-second and 30-second windows.

分享這個問答