Mutating counts without cleanup
Wrong move: Zero-count keys stay in map and break distinct/count constraints.
Usually fails on: Window/map size checks are consistently off by one.
Fix: Delete keys when count reaches zero.
Move from brute-force thinking to an efficient approach using hash map strategy.
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:
[10,69], [70,129], [130,189], ..., [9970,10000][10,3609], [3610,7209], [7210,10000][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 (10000 in the above example).
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.Example:
Input
["TweetCounts","recordTweet","recordTweet","recordTweet","getTweetCountsPerFrequency","getTweetCountsPerFrequency","recordTweet","getTweetCountsPerFrequency"]
[[],["tweet3",0],["tweet3",60],["tweet3",10],["minute","tweet3",0,59],["minute","tweet3",0,60],["tweet3",120],["hour","tweet3",0,210]]
Output
[null,null,null,null,[2],[2,1],null,[4]]
Explanation
TweetCounts tweetCounts = new TweetCounts();
tweetCounts.recordTweet("tweet3", 0); // New tweet "tweet3" at time 0
tweetCounts.recordTweet("tweet3", 60); // New tweet "tweet3" at time 60
tweetCounts.recordTweet("tweet3", 10); // New tweet "tweet3" at time 10
tweetCounts.getTweetCountsPerFrequency("minute", "tweet3", 0, 59); // return [2]; chunk [0,59] had 2 tweets
tweetCounts.getTweetCountsPerFrequency("minute", "tweet3", 0, 60); // return [2,1]; chunk [0,59] had 2 tweets, chunk [60,60] had 1 tweet
tweetCounts.recordTweet("tweet3", 120); // New tweet "tweet3" at time 120
tweetCounts.getTweetCountsPerFrequency("hour", "tweet3", 0, 210); // return [4]; chunk [0,210] had 4 tweets
Constraints:
0 <= time, startTime, endTime <= 1090 <= endTime - startTime <= 104104 calls in total to recordTweet and getTweetCountsPerFrequency.Problem summary: 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 (10000 in the above example). Design and implement an API to help the company with their analysis. Implement the TweetCounts class: TweetCounts() Initializes the TweetCounts object. void
Start with the most direct exhaustive search. That gives a correctness anchor before optimizing.
Pattern signal: Hash Map · Binary Search · Design · Segment Tree
["TweetCounts","recordTweet","recordTweet","recordTweet","getTweetCountsPerFrequency","getTweetCountsPerFrequency","recordTweet","getTweetCountsPerFrequency"] [[],["tweet3",0],["tweet3",60],["tweet3",10],["minute","tweet3",0,59],["minute","tweet3",0,60],["tweet3",120],["hour","tweet3",0,210]]
design-video-sharing-platform)Source-backed implementations are provided below for direct study and interview prep.
// Accepted solution for LeetCode #1348: Tweet Counts Per Frequency
class TweetCounts {
private Map<String, TreeMap<Integer, Integer>> data = new HashMap<>();
public TweetCounts() {
}
public void recordTweet(String tweetName, int time) {
data.putIfAbsent(tweetName, new TreeMap<>());
var tm = data.get(tweetName);
tm.put(time, tm.getOrDefault(time, 0) + 1);
}
public List<Integer> getTweetCountsPerFrequency(
String freq, String tweetName, int startTime, int endTime) {
int f = 60;
if ("hour".equals(freq)) {
f = 3600;
} else if ("day".equals(freq)) {
f = 86400;
}
var tm = data.get(tweetName);
List<Integer> ans = new ArrayList<>();
for (int i = startTime; i <= endTime; i += f) {
int s = 0;
int end = Math.min(i + f, endTime + 1);
for (int v : tm.subMap(i, end).values()) {
s += v;
}
ans.add(s);
}
return ans;
}
}
/**
* Your TweetCounts object will be instantiated and called as such:
* TweetCounts obj = new TweetCounts();
* obj.recordTweet(tweetName,time);
* List<Integer> param_2 = obj.getTweetCountsPerFrequency(freq,tweetName,startTime,endTime);
*/
// Accepted solution for LeetCode #1348: Tweet Counts Per Frequency
// Auto-generated Go example from java.
func exampleSolution() {
}
// Reference (java):
// // Accepted solution for LeetCode #1348: Tweet Counts Per Frequency
// class TweetCounts {
// private Map<String, TreeMap<Integer, Integer>> data = new HashMap<>();
//
// public TweetCounts() {
// }
//
// public void recordTweet(String tweetName, int time) {
// data.putIfAbsent(tweetName, new TreeMap<>());
// var tm = data.get(tweetName);
// tm.put(time, tm.getOrDefault(time, 0) + 1);
// }
//
// public List<Integer> getTweetCountsPerFrequency(
// String freq, String tweetName, int startTime, int endTime) {
// int f = 60;
// if ("hour".equals(freq)) {
// f = 3600;
// } else if ("day".equals(freq)) {
// f = 86400;
// }
// var tm = data.get(tweetName);
// List<Integer> ans = new ArrayList<>();
// for (int i = startTime; i <= endTime; i += f) {
// int s = 0;
// int end = Math.min(i + f, endTime + 1);
// for (int v : tm.subMap(i, end).values()) {
// s += v;
// }
// ans.add(s);
// }
// return ans;
// }
// }
//
// /**
// * Your TweetCounts object will be instantiated and called as such:
// * TweetCounts obj = new TweetCounts();
// * obj.recordTweet(tweetName,time);
// * List<Integer> param_2 = obj.getTweetCountsPerFrequency(freq,tweetName,startTime,endTime);
// */
# Accepted solution for LeetCode #1348: Tweet Counts Per Frequency
class TweetCounts:
def __init__(self):
self.d = {"minute": 60, "hour": 3600, "day": 86400}
self.data = defaultdict(SortedList)
def recordTweet(self, tweetName: str, time: int) -> None:
self.data[tweetName].add(time)
def getTweetCountsPerFrequency(
self, freq: str, tweetName: str, startTime: int, endTime: int
) -> List[int]:
f = self.d[freq]
tweets = self.data[tweetName]
t = startTime
ans = []
while t <= endTime:
l = tweets.bisect_left(t)
r = tweets.bisect_left(min(t + f, endTime + 1))
ans.append(r - l)
t += f
return ans
# Your TweetCounts object will be instantiated and called as such:
# obj = TweetCounts()
# obj.recordTweet(tweetName,time)
# param_2 = obj.getTweetCountsPerFrequency(freq,tweetName,startTime,endTime)
// Accepted solution for LeetCode #1348: Tweet Counts Per Frequency
use std::collections::BTreeMap;
use std::collections::HashMap;
const SECONDS: [usize; 3] = [60, 3600, 86400];
#[derive(Default)]
struct TweetCounts {
data: HashMap<String, BTreeMap<usize, usize>>,
}
impl TweetCounts {
fn new() -> Self {
TweetCounts::default()
}
fn record_tweet(&mut self, tweet_name: String, time: i32) {
let time = time as usize;
*self
.data
.entry(tweet_name)
.or_default()
.entry(time)
.or_default() += 1;
}
fn get_tweet_counts_per_frequency(
&self,
freq: String,
tweet_name: String,
start_time: i32,
end_time: i32,
) -> Vec<i32> {
let seconds = SECONDS[Self::freq_to_index(&freq)];
let start_time = start_time as usize;
let end_time = end_time as usize;
let n = (end_time - start_time) / seconds + 1;
let mut res = vec![0; n];
if let Some(counts) = self.data.get(&tweet_name) {
for (&t, &c) in counts {
let i = (t - start_time) / seconds;
if t >= start_time && t <= end_time {
res[i] += c as i32;
}
}
}
res
}
fn freq_to_index(freq: &str) -> usize {
match freq {
"minute" => 0,
"hour" => 1,
"day" => 2,
_ => panic!(),
}
}
}
#[test]
fn test() {
let mut obj = TweetCounts::new();
obj.record_tweet("tweet3".to_string(), 0);
obj.record_tweet("tweet3".to_string(), 60);
obj.record_tweet("tweet3".to_string(), 10);
assert_eq!(
obj.get_tweet_counts_per_frequency("minute".to_string(), "tweet3".to_string(), 0, 59),
vec![2]
);
assert_eq!(
obj.get_tweet_counts_per_frequency("minute".to_string(), "tweet3".to_string(), 0, 60),
vec![2, 1]
);
obj.record_tweet("tweet3".to_string(), 120);
assert_eq!(
obj.get_tweet_counts_per_frequency("hour".to_string(), "tweet3".to_string(), 0, 210),
vec![4]
);
}
// Accepted solution for LeetCode #1348: Tweet Counts Per Frequency
// Auto-generated TypeScript example from java.
function exampleSolution(): void {
}
// Reference (java):
// // Accepted solution for LeetCode #1348: Tweet Counts Per Frequency
// class TweetCounts {
// private Map<String, TreeMap<Integer, Integer>> data = new HashMap<>();
//
// public TweetCounts() {
// }
//
// public void recordTweet(String tweetName, int time) {
// data.putIfAbsent(tweetName, new TreeMap<>());
// var tm = data.get(tweetName);
// tm.put(time, tm.getOrDefault(time, 0) + 1);
// }
//
// public List<Integer> getTweetCountsPerFrequency(
// String freq, String tweetName, int startTime, int endTime) {
// int f = 60;
// if ("hour".equals(freq)) {
// f = 3600;
// } else if ("day".equals(freq)) {
// f = 86400;
// }
// var tm = data.get(tweetName);
// List<Integer> ans = new ArrayList<>();
// for (int i = startTime; i <= endTime; i += f) {
// int s = 0;
// int end = Math.min(i + f, endTime + 1);
// for (int v : tm.subMap(i, end).values()) {
// s += v;
// }
// ans.add(s);
// }
// return ans;
// }
// }
//
// /**
// * Your TweetCounts object will be instantiated and called as such:
// * TweetCounts obj = new TweetCounts();
// * obj.recordTweet(tweetName,time);
// * List<Integer> param_2 = obj.getTweetCountsPerFrequency(freq,tweetName,startTime,endTime);
// */
Use this to step through a reusable interview workflow for this problem.
Check every element from left to right until we find the target or exhaust the array. Each comparison is O(1), and we may visit all n elements, giving O(n). No extra space needed.
Each comparison eliminates half the remaining search space. After k comparisons, the space is n/2ᵏ. We stop when the space is 1, so k = log₂ n. No extra memory needed — just two pointers (lo, hi).
Review these before coding to avoid predictable interview regressions.
Wrong move: Zero-count keys stay in map and break distinct/count constraints.
Usually fails on: Window/map size checks are consistently off by one.
Fix: Delete keys when count reaches zero.
Wrong move: Setting `lo = mid` or `hi = mid` can stall and create an infinite loop.
Usually fails on: Two-element ranges never converge.
Fix: Use `lo = mid + 1` or `hi = mid - 1` where appropriate.