355. Design Twitter

设计一个简化版的推特(Twitter),可以让用户实现发送推文,关注/取消关注其他用户,能够看见关注人(包括自己)的最近十条推文。

你的设计需要支持以下的几个功能:

  • postTweet(userId, tweetId): 创建一条新的推文
  • getNewsFeed(userId): 检索最近的十条推文。每个推文都必须是由此用户关注的人或者是用户自己发出的。推文必须按照时间顺序由最近的开始排序。
  • follow(followerId, followeeId): 关注一个用户
  • unfollow(followerId, followeeId): 取消关注一个用户
355. 设计推特
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
public class Twitter {
private static int timeStamp=0;

// easy to find if user exist
private Map<Integer, User> userMap;

// Tweet link to next Tweet so that we can save a lot of time
// when we execute getNewsFeed(userId)
private class Tweet{
public int id;
public int time;
public Tweet next;

public Tweet(int id){
this.id = id;
time = timeStamp++;
next=null;
}
}

// OO design so User can follow, unfollow and post itself
public class User{
public int id;
public Set<Integer> followed;
public Tweet tweet_head;

public User(int id){
this.id=id;
followed = new HashSet<>();
follow(id); // first follow itself
tweet_head = null;
}
public void follow(int id){
followed.add(id);
}
public void unfollow(int id){
followed.remove(id);
}

// everytime user post a new tweet, add it to the head of tweet list.
public void post(int id){
Tweet t = new Tweet(id);
t.next=tweet_head;
tweet_head=t;
}
}

/** Initialize your data structure here. */
public Twitter() {
userMap = new HashMap<Integer, User>();
}

/** Compose a new tweet. */
public void postTweet(int userId, int tweetId) {
if(!userMap.containsKey(userId)){
User u = new User(userId);
userMap.put(userId, u);
}
userMap.get(userId).post(tweetId);
}

// Best part of this.
// first get all tweets lists from one user including itself and all people it followed.
// Second add all heads into a max heap. Every time we poll a tweet with
// largest time stamp from the heap, then we add its next tweet into the heap.
// So after adding all heads we only need to add 9 tweets at most into this
// heap before we get the 10 most recent tweet.
public List<Integer> getNewsFeed(int userId) {
List<Integer> res = new LinkedList<>();

if(!userMap.containsKey(userId)) return res;

Set<Integer> users = userMap.get(userId).followed;
PriorityQueue<Tweet> q = new PriorityQueue<Tweet>(users.size(), (a,b)->(b.time-a.time));
for(int user: users){
Tweet t = userMap.get(user).tweet_head;
// very imporant! If we add null to the head we are screwed.
if(t!=null){
q.add(t);
}
}
int n=0;
while(!q.isEmpty() && n<10){
Tweet t = q.poll();
res.add(t.id);
n++;
if(t.next!=null)
q.add(t.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(!userMap.containsKey(followerId)){
User u = new User(followerId);
userMap.put(followerId, u);
}
if(!userMap.containsKey(followeeId)){
User u = new User(followeeId);
userMap.put(followeeId, u);
}
userMap.get(followerId).follow(followeeId);
}

/** Follower unfollows a followee. If the operation is invalid, it should be a no-op. */
public void unfollow(int followerId, int followeeId) {
if(!userMap.containsKey(followerId) || followerId==followeeId)
return;
userMap.get(followerId).unfollow(followeeId);
}
}
/**
* Your Twitter object will be instantiated and called as such:
* Twitter obj = new Twitter();
* obj.postTweet(userId,tweetId);
* List<Integer> param_2 = obj.getNewsFeed(userId);
* obj.follow(followerId,followeeId);
* obj.unfollow(followerId,followeeId);
*/

0%