forked from fishercoder1534/Leetcode
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy path_355.java
281 lines (244 loc) · 9.6 KB
/
_355.java
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
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
package com.fishercoder.solutions;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.PriorityQueue;
import java.util.Set;
public class _355 {
public static class Solution1 {
/**
* reference: https://discuss.leetcode.com/topic/48100/java-oo-design-with-most-efficient-function-getnewsfeed
*/
public static class Twitter {
private static int timestamp = 0;
private Map<Integer, User> map;
class Tweet {
public int time;
public int id;
public Tweet next;
/**
* have a pointer,
* so we could be more memory efficient when retrieving tweets,
* think about merging k sorted lists
*/
public Tweet(int id) {
this.id = id;
time = timestamp++;
next = null;
}
}
/**
* the meat part of this OO design problem,
* have a User object itself,
* have follow() and unfollow() method embedded inside it
*/
class User {
public int id;
public Set<Integer> followed;
public Tweet tweetHead;
public User(int id) {
this.id = id;
followed = new HashSet<>();
followed.add(id);//follow oneself first
this.tweetHead = null;
}
public void follow(int followeeId) {
followed.add(followeeId);
}
public void unfollow(int followeeId) {
followed.remove(followeeId);
}
public void postTweet(int tweetId) {
//every time we post, we prepend it to the head of the tweet
Tweet head = new Tweet(tweetId);
head.next = tweetHead;
tweetHead = head;//don't forget to overwrite tweetHead with the new head
}
}
/**
* Initialize your data structure here.
*/
public Twitter() {
map = new HashMap();
}
/**
* Compose a new tweet.
*/
public void postTweet(int userId, int tweetId) {
/**update oneself newsFeed first and also all of his followers' newsFeed*/
if (!map.containsKey(userId)) {
User user = new User(userId);
map.put(userId, user);
}
map.get(userId).postTweet(tweetId);
}
/**
* 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) {
List<Integer> newsFeed = new LinkedList<>();
if (!map.containsKey(userId)) {
return newsFeed;
}
Set<Integer> users = map.get(userId).followed;
PriorityQueue<Tweet> heap = new PriorityQueue<>(users.size(), (a, b) -> b.time - a.time);
for (int user : users) {
Tweet tweet = map.get(user).tweetHead;
//it's super important to check null before putting into the heap
if (tweet != null) {
heap.offer(tweet);
}
}
int count = 0;
while (!heap.isEmpty() && count < 10) {
Tweet tweet = heap.poll();
newsFeed.add(tweet.id);
count++;
if (tweet.next != null) {
heap.offer(tweet.next);
}
}
return newsFeed;
}
/**
* Follower follows a followee. If the operation is invalid, it should be a no-op.
*/
public void follow(int followerId, int followeeId) {
if (!map.containsKey(followeeId)) {
User user = new User(followeeId);
map.put(followeeId, user);
}
if (!map.containsKey(followerId)) {
User user = new User(followerId);
map.put(followerId, user);
}
map.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 (!map.containsKey(followerId) || followeeId == followerId) {
return;
}
map.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);
*/
}
}
public static class Solution2 {
public static class Twitter {
Map<Integer, User> map;
private int timestamp;
private class User {
private int userId;
private Set<Integer> followed;
private Tweet tweetHead;
public User(int userId) {
this.userId = userId;
this.followed = new HashSet<>();
this.followed.add(userId);
this.tweetHead = null;
}
public void postTweet(int tweetId) {
Tweet tweet = new Tweet(tweetId);
tweet.next = tweetHead;
tweetHead = tweet;
}
public void follow(int followeeId) {
followed.add(followeeId);
}
public void unfollow(int followeeId) {
followed.remove(followeeId);
}
}
private class Tweet {
int time;
int id;
Tweet next;
public Tweet(int id) {
this.id = id;
time = timestamp++;
next = null;
}
}
/**
* Initialize your data structure here.
*/
public Twitter() {
map = new HashMap<>();
timestamp = 0;
}
/**
* Compose a new tweet.
*/
public void postTweet(int userId, int tweetId) {
if (!map.containsKey(userId)) {
User user = new User(userId);
map.put(userId, user);
}
map.get(userId).postTweet(tweetId);
}
/**
* 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) {
List<Integer> result = new LinkedList<>();
if (!map.containsKey(userId)) {
return result;
}
Set<Integer> followeeSet = map.get(userId).followed;
PriorityQueue<Tweet> maxHeap = new PriorityQueue<>((a, b) -> b.time - a.time);
for (int followeeId : followeeSet) {
if (map.containsKey(followeeId)) {
Tweet tweet = map.get(followeeId).tweetHead;
if (tweet != null) {
maxHeap.offer(tweet);
}
}
}
int count = 0;
while (!maxHeap.isEmpty() && count++ < 10) {
Tweet tweet = maxHeap.poll();
if (tweet != null) {
result.add(tweet.id);
if (tweet.next != null) {
maxHeap.offer(tweet.next);
}
}
}
return result;
}
/**
* Follower follows a followee. If the operation is invalid, it should be a no-op.
*/
public void follow(int followerId, int followeeId) {
if (!map.containsKey(followerId)) {
map.put(followerId, new User(followerId));
}
if (!map.containsKey(followeeId)) {
map.put(followeeId, new User(followeeId));
}
map.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 (!map.containsKey(followerId) || followeeId == followerId) {
return;
}
map.get(followerId).unfollow(followeeId);
}
}
}
}