方法
Tweet类实现: 每个 Tweet 实例需要记录自己的 tweetId 和发表时间 time,而且作为链表节点,要有一个指向下一个 Tweet 节点的 next 指针。
User类实现: 一个用户需要存储的信息有 userId,关注列表 (用HashSet方便快速查找),以及该用户发过的推文列表 (只存储其推文链表的头节点即可)。推文列表使用链表实现,便于进行有序合并的操作。
getNewsFeed()方法实现: 把每个用户各自的推文存储在链表里,这个链表是按 time 有序的。 如果某个用户关注了 k 个用户,可以用合并 k 个有序链表的算法合并出有序的推文列表,实现 getNewsFeed()
class Twitter {
public class Tweet {
Tweet next;
int id;
int timestamp; // sort tweet by time
Tweet(int id, int timestamp) {
this.id = id;
this.timestamp = timestamp;
}
}
public class User {
public int id;
public Set<Integer> followed;
public Tweet head; // head of tweet linkedlist
public User(int id) {
this.id = id;
followed = new HashSet<>();
followed.add(id); // self follow, to get self tweet
}
public void follow(int id) {
followed.add(id);
}
public void unfollow(int id) {
followed.remove(id);
}
// add a tweet node to head
public void post(int tweetId, int timestamp) {
Tweet t = new Tweet(tweetId, timestamp);
t.next = head;
head = t;
}
}
// global 时间戳
int timestamp = 0;
Map<Integer, User> userMap; // for convenience
public Twitter() {
userMap = new HashMap<>();
}
public void postTweet(int userId, int tweetId) {
// new user
if (!userMap.containsKey(userId)) {
userMap.put(userId, new User(userId));
}
userMap.get(userId).post(tweetId, timestamp);
timestamp++; // time goes
}
public List<Integer> getNewsFeed(int userId) {
List<Integer> res = new ArrayList<>();
if (!userMap.containsKey(userId)) {
return res;
}
Set<Integer> users = userMap.get(userId).followed;
// time大的tweet排在前面
Queue<Tweet> pq = new PriorityQueue<>((a, b) -> (b.timestamp - a.timestamp));
// 把follwee的 tweet头节点 塞到pq里
for (int user : users) {
Tweet t = userMap.get(user).head;
if (t != null) {
pq.add(t);
}
}
int count = 0; // shoud be less than 10
while (!pq.isEmpty() && count < 10) {
Tweet t = pq.poll();
res.add(t.id);
count++;
// 下一个节点也要加进pq
if (t.next != null) {
pq.add(t.next);
}
}
return res;
}
public void follow(int followerId, int followeeId) {
if (!userMap.containsKey(followerId)) {
userMap.put(followerId, new User(followerId));
}
if (!userMap.containsKey(followeeId)) {
userMap.put(followeeId, new User(followeeId));
}
userMap.get(followerId).follow(followeeId);
}
public void unfollow(int followerId, int followeeId) {
if (!userMap.containsKey(followerId)) {
return;
}
userMap.get(followerId).unfollow(followeeId);
}
}