A social media company is trying to monitor activity on their site by analyzing the number of tweets that occur in select periods of time. These periods can be partitioned into smaller time chunks based on a certain frequency (every minute, hour, or day).
For example, the period [10, 10000] (in seconds) would be partitioned into the following time chunks with these frequencies:
Every minute (60-second chunks): [10,69], [70,129], [130,189], ..., [9970,10000]
Every hour (3600-second chunks): [10,3609], [3610,7209], [7210,10000]
Every day (86400-second chunks): [10,10000]
Notice that the last chunk may be shorter than the specified frequency's chunk size and will always end with the end time of the period.
Design and implement an API to help the company with their analysis.
Implement the TweetCounts class:
TweetCounts() Initializes the TweetCounts object.
void recordTweet(String tweetName, int time) Stores the tweetName at the recorded time (in seconds).
List<Integer> getTweetCountsPerFrequency(String freq, String tweetName, int startTime, int endTime) Returns a list of integers representing the number of tweets with tweetName in each time chunk for the given period of time [startTime, endTime] (in seconds) and frequency freq.
freq is one of "minute", "hour", or "day" representing a frequency of every minute, hour, or day respectively.
💡 Note:Initialize TweetCounts, record tweet3 at time 0, record tweet3 at time 60, then query minute frequency for tweet3 from 0 to 59. Only the tweet at time 0 falls in range [0,59].
💡 Note:Record tweets at 100, 3700, 7300. Query hour frequency [0,7199] creates one chunk [0,3599] containing tweets at 100 and 3700 (7300 is outside range).
Constraints
0 ≤ time ≤ 109
0 ≤ startTime ≤ endTime ≤ 109
freq is one of "minute", "hour", or "day"
At most 104 calls to recordTweet and getTweetCountsPerFrequency
The key insight is to use a HashMap to group timestamps by tweet name, and maintain them in sorted order for efficient range queries. The optimized approach uses binary search to find timestamp ranges in O(log n) time per chunk. Best approach: Binary Search with Time: O(c × log n), Space: O(n).
Common Approaches
✓
Brute Force - Linear Search
⏱️ Time: O(n × c)
Space: O(n)
For each tweet name, store all timestamps in a list. When querying, iterate through all timestamps and count those within each time chunk.
Optimized - Binary Search
⏱️ Time: O(c × log n)
Space: O(n)
Store timestamps for each tweet name in sorted order. For each time chunk, use binary search to find the range of timestamps and count them efficiently.
Brute Force - Linear Search — Algorithm Steps
Store all tweet timestamps in lists grouped by name
For each query, scan all timestamps linearly
Count tweets falling in each time chunk
Visualization
Tap to expand
Step-by-Step Walkthrough
1
Store Tweets
Add timestamps to lists by tweet name
2
Linear Search
For each chunk, scan all timestamps
3
Count Matches
Count timestamps within chunk range
Code -
solution.c — C
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_TWEETS 10000
#define MAX_NAME_LEN 100
#define MAX_OPERATIONS 1000
#define MAX_STRINGS 10
#define MAX_INTS 10
typedef struct {
char names[MAX_TWEETS][MAX_NAME_LEN];
int times[MAX_TWEETS];
int count;
} TweetCounts;
typedef struct {
char stringVals[MAX_STRINGS][MAX_NAME_LEN];
int stringCount;
int intVals[MAX_INTS];
int intCount;
} ParamSet;
TweetCounts* tweetCountsCreate() {
TweetCounts* obj = (TweetCounts*)malloc(sizeof(TweetCounts));
obj->count = 0;
return obj;
}
void tweetCountsRecordTweet(TweetCounts* obj, char* tweetName, int time) {
strcpy(obj->names[obj->count], tweetName);
obj->times[obj->count] = time;
obj->count++;
}
int* tweetCountsGetTweetCountsPerFrequency(TweetCounts* obj, char* freq, char* tweetName, int startTime, int endTime, int* returnSize) {
int interval;
if (strcmp(freq, "minute") == 0) interval = 60;
else if (strcmp(freq, "hour") == 0) interval = 3600;
else interval = 86400;
int* result = (int*)malloc(1000 * sizeof(int));
*returnSize = 0;
int current = startTime;
while (current <= endTime) {
int chunkEnd = (current + interval - 1 < endTime) ? current + interval - 1 : endTime;
int count = 0;
for (int i = 0; i < obj->count; i++) {
if (strcmp(obj->names[i], tweetName) == 0 && obj->times[i] >= current && obj->times[i] <= chunkEnd) {
count++;
}
}
result[*returnSize] = count;
(*returnSize)++;
current += interval;
}
return result;
}
void parseStringArray(const char* str, char operations[][20], int* opCount) {
*opCount = 0;
const char* p = str;
while (*p && *p != '[') p++;
if (*p == '[') p++;
while (*p && *p != ']') {
while (*p == ' ' || *p == ',') p++;
if (*p == ']' || *p == '\0') break;
if (*p == '"') {
p++;
int len = 0;
while (*p && *p != '"') {
operations[*opCount][len++] = *p++;
}
operations[*opCount][len] = '\0';
(*opCount)++;
if (*p == '"') p++;
} else {
p++;
}
}
}
void parseParams(const char* str, ParamSet* params, int* paramCount) {
*paramCount = 0;
const char* p = str;
while (*p && *p != '[') p++;
if (*p == '[') p++;
while (*p && *p != ']') {
while (*p == ' ' || *p == ',') p++;
if (*p == ']' || *p == '\0') break;
if (*p == '[') {
p++;
params[*paramCount].stringCount = 0;
params[*paramCount].intCount = 0;
while (*p && *p != ']') {
while (*p == ' ' || *p == ',') p++;
if (*p == ']') break;
if (*p == '"') {
p++;
int len = 0;
while (*p && *p != '"') {
params[*paramCount].stringVals[params[*paramCount].stringCount][len++] = *p++;
}
params[*paramCount].stringVals[params[*paramCount].stringCount][len] = '\0';
params[*paramCount].stringCount++;
if (*p == '"') p++;
} else if ((*p >= '0' && *p <= '9') || *p == '-') {
int negative = 0;
if (*p == '-') {
negative = 1;
p++;
}
int num = 0;
while (*p >= '0' && *p <= '9') {
num = num * 10 + (*p - '0');
p++;
}
if (negative) num = -num;
params[*paramCount].intVals[params[*paramCount].intCount++] = num;
} else {
p++;
}
}
if (*p == ']') p++;
(*paramCount)++;
} else {
p++;
}
}
}
int main() {
char line1[100000];
char line2[100000];
if (fgets(line1, sizeof(line1), stdin) == NULL) {
printf("[]\n");
return 0;
}
line1[strcspn(line1, "\n\r")] = '\0';
if (fgets(line2, sizeof(line2), stdin) == NULL) {
printf("[]\n");
return 0;
}
line2[strcspn(line2, "\n\r")] = '\0';
char operations[MAX_OPERATIONS][20];
int opCount;
parseStringArray(line1, operations, &opCount);
ParamSet params[MAX_OPERATIONS];
int paramCount;
parseParams(line2, params, ¶mCount);
TweetCounts* obj = NULL;
static int results[MAX_OPERATIONS][1000];
int resultSizes[MAX_OPERATIONS];
int resultCount = 0;
for (int i = 0; i < opCount; i++) {
if (strcmp(operations[i], "TweetCounts") == 0) {
obj = tweetCountsCreate();
resultSizes[resultCount++] = -1;
} else if (strcmp(operations[i], "recordTweet") == 0) {
tweetCountsRecordTweet(obj, params[i].stringVals[0], params[i].intVals[0]);
resultSizes[resultCount++] = -1;
} else if (strcmp(operations[i], "getTweetCountsPerFrequency") == 0) {
int size;
int* result = tweetCountsGetTweetCountsPerFrequency(obj, params[i].stringVals[0], params[i].stringVals[1], params[i].intVals[0], params[i].intVals[1], &size);
for (int j = 0; j < size; j++) {
results[resultCount][j] = result[j];
}
resultSizes[resultCount++] = size;
free(result);
}
}
printf("[");
for (int i = 0; i < resultCount; i++) {
if (i > 0) printf(",");
if (resultSizes[i] == -1) {
printf("null");
} else {
printf("[");
for (int j = 0; j < resultSizes[i]; j++) {
if (j > 0) printf(",");
printf("%d", results[i][j]);
}
printf("]");
}
}
printf("]\n");
if (obj) free(obj);
return 0;
}
Time & Space Complexity
Time Complexity
⏱️
O(n × c)
n timestamps scanned × c time chunks per query
n
2n
⚡ Linearithmic
Space Complexity
O(n)
HashMap storing n tweet timestamps
n
2n
⚡ Linearithmic Space
28.5K Views
MediumFrequency
~25 minAvg. Time
847 Likes
Ln 1, Col 1
Smart Actions
💡Explanation
AI Ready
💡 SuggestionTabto acceptEscto dismiss
// Output will appear here after running code
Code Editor Closed
Click the red button to reopen
Algorithm Visualization
Pinch to zoom • Tap outside to close
Test Cases
0 passed
0 failed
3 pending
Select Compiler
Choose a programming language
Compiler list would appear here...
AI Editor Features
Header Buttons
💡
Explain
Get a detailed explanation of your code. Select specific code or analyze the entire file. Understand algorithms, logic flow, and complexity.
🔧
Fix
Automatically detect and fix issues in your code. Finds bugs, syntax errors, and common mistakes. Shows you what was fixed.
💡
Suggest
Get improvement suggestions for your code. Best practices, performance tips, and code quality recommendations.
💬
Ask AI
Open an AI chat assistant to ask any coding questions. Have a conversation about your code, get help with debugging, or learn new concepts.
Smart Actions (Slash Commands)
🔧
/fix Enter
Find and fix issues in your code. Detects common problems and applies automatic fixes.
💡
/explain Enter
Get a detailed explanation of what your code does, including time/space complexity analysis.
🧪
/tests Enter
Automatically generate unit tests for your code. Creates comprehensive test cases.
📝
/docs Enter
Generate documentation for your code. Creates docstrings, JSDoc comments, and type hints.
⚡
/optimize Enter
Get performance optimization suggestions. Improve speed and reduce memory usage.
AI Code Completion (Copilot-style)
👻
Ghost Text Suggestions
As you type, AI suggests code completions shown in gray text. Works with keywords like def, for, if, etc.
Tabto acceptEscto dismiss
💬
Comment-to-Code
Write a comment describing what you want, and AI generates the code. Try: # two sum, # binary search, # fibonacci
💡
Pro Tip: Select specific code before using Explain, Fix, or Smart Actions to analyze only that portion. Otherwise, the entire file will be analyzed.