一、题目
设计一个简化版的推特(Twitter),可以让用户实现发送推文,关注/取消关注其他用户,能够看见关注人(包括自己)的最近十条推文。你的设计需要支持以下的几个功能:
postTweet(userId, tweetId): 创建一条新的推文
getNewsFeed(userId): 检索最近的十条推文。每个推文都必须是由此用户关注的人或者是用户自己发出的。推文必须按照时间顺序由最近的开始排序。
follow(followerId, followeeId): 关注一个用户
unfollow(followerId, followeeId): 取消关注一个用户
二、思路
使用map+链表的方式存储Tweet,使用优先队列检索最近的十条推文。
三、实现
public class Twitter {
private int timestamp = 0;
private Map<Integer, Tweet> userTweetMap = new HashMap<>();
private Map<Integer, Set<Integer>> userFollowMap = new HashMap<>();
public Twitter() {
}
/**
* Compose a new tweet.
*/
public void postTweet(int userId, int tweetId) {
timestamp++;
Tweet tweet = new Tweet(tweetId, timestamp);
if (userTweetMap.containsKey(userId)) {
Tweet oldTweet = userTweetMap.get(userId);
tweet.next = oldTweet;
}
userTweetMap.put(userId, tweet);
}
/**
* Retrieve the 10 most recent tweet ids in the user's news feed. Each item in the news feed must be posted by users who the user followed or by the user herself. Tweets must be ordered from most recent to least recent.
*/
public List<Integer> getNewsFeed(int userId) {
PriorityQueue<Tweet> queue = new PriorityQueue<>((o1, o2) -> o2.time - o1.time);
if (userTweetMap.containsKey(userId)) {
queue.offer(userTweetMap.get(userId));
}
Set<Integer> followers = userFollowMap.get(userId);
if (followers != null) {
for (int followerId : followers) {
if (userTweetMap.containsKey(followerId)) {
queue.offer(userTweetMap.get(followerId));
}
}
}
List<Integer> res = new ArrayList<>(10);
while (queue.size() != 0 && res.size() < 10) {
Tweet head = queue.poll();
res.add(head.twId);
if (head.next != null) {
queue.offer(head.next);
}
}
return res;
}
/**
* Follower follows a followee. If the operation is invalid, it should be a no-op.
*/
public void follow(int followerId, int followeeId) {
if (followeeId == followerId) {
return;
}
if (userFollowMap.containsKey(followerId)) {
Set<Integer> set = userFollowMap.get(followerId);
set.add(followeeId);
userFollowMap.put(followerId, set);
} else {
Set<Integer> set = new HashSet<>();
set.add(followeeId);
userFollowMap.put(followerId, set);
}
}
/**
* Follower unfollows a followee. If the operation is invalid, it should be a no-op.
*/
public void unfollow(int followerId, int followeeId) {
if (userFollowMap.containsKey(followerId)) {
Set<Integer> set = userFollowMap.get(followerId);
set.remove(followeeId);
}
}
class Tweet {
int twId;
int time;
Tweet next;
public Tweet(int twId, int time) {
this.twId = twId;
this.time = time;
}
}
}