Implement a simple twitter. Support the following method:
postTweet(user_id, tweet_text)
. Post a tweet.getTimeline(user_id)
. Get the given user's most recently 10 tweets posted by himself, order by timestamp from most recent to least recent.getNewsFeed(user_id)
. Get the given user's most recently 10 tweets in his news feed (posted by his friends and himself). Order by timestamp from most recent to least recent.follow(from_user_id, to_user_id)
. from_user_id followed to_user_id.unfollow(from_user_id, to_user_id)
. from_user_id unfollowed to to_user_id.
Example
Example 1:
Input:
postTweet(1, "LintCode is Good!!!")
getNewsFeed(1)
getTimeline(1)
follow(2, 1)
getNewsFeed(2)
unfollow(2, 1)
getNewsFeed(2)
Output:
1
[1]
[1]
[1]
[]
思路:这题首先考虑到需要什么数据结构,
首先,需要timestamp,那么需要int,需要一个Node class去包装tweet,和timestamp;
post 可以是顺序的,所以hashmap<Integer, List<Node>>足够,fans,HashMap<Integer, HashSet<Integer>>()可以;最后,注意的点是:每次取是从每个人post的屁股后面取,因为后面是最大的,然后用最小堆就可以求出所有的最大值;然后逆序输出就行了;
/**
* Definition of Tweet:
* public class Tweet {
* public int id;
* public int user_id;
* public String text;
* public static Tweet create(int user_id, String tweet_text) {
* // This will create a new tweet object,
* // and auto fill id
* }
* }
*/
public class MiniTwitter {
private class Node {
public Tweet tweet;
public int time;
public Node(Tweet tweet, int time) {
this.tweet = tweet;
this.time = time;
}
}
private class NodeComparator implements Comparator<Node> {
@Override
public int compare(Node a, Node b) {
return a.time - b.time;
}
}
private HashMap<Integer, List<Node>> userTweets;
private HashMap<Integer, HashSet<Integer>> fans;
private int time;
public MiniTwitter() {
this.userTweets = new HashMap<Integer, List<Node>>();
this.fans = new HashMap<Integer, HashSet<Integer>>();
this.time = 0;
}
/*
* @param user_id: An integer
* @param tweet_text: a string
* @return: a tweet
*/
public Tweet postTweet(int user_id, String tweet_text) {
userTweets.putIfAbsent(user_id, new ArrayList<Node>());
Tweet newtweet = Tweet.create(user_id, tweet_text);
userTweets.get(user_id).add(new Node(newtweet, ++time));
follow(user_id, user_id);
return newtweet;
}
/*
* @param user_id: An integer
* @return: a list of 10 new feeds recently and sort by timeline
*/
private List<Node> getLastTenTweet(List<Node> list) {
List<Node> result = new ArrayList<Node>();
// 记住,是从每个fans post里面最大的开始拿起
// 所以 getLastTenTweet 要从最后开始拿;
for(int i = list.size() -1; i >= Math.max(0, list.size() -10); i--){
result.add(list.get(i));
}
return result;
}
public List<Tweet> getNewsFeed(int user_id) {
List<Tweet> result = new ArrayList<Tweet>();
PriorityQueue<Node> pq = new PriorityQueue<Node>(10, new NodeComparator());
if(fans.containsKey(user_id)) {
for(Integer fans_id: fans.get(user_id)) {
if(userTweets.containsKey(fans_id)) {
List<Node> posts = userTweets.get(fans_id);
for(Node node: getLastTenTweet(posts)) {
// 记住,是从每个fans post里面最大的开始拿起;
// 所以 getLastTenTweet 要从最后开始拿;
pq.add(node);
if(pq.size() > 10){
pq.poll();
}
}
}
}
}
while(!pq.isEmpty()) {
result.add(0, pq.poll().tweet);
}
return result;
}
/*
* @param user_id: An integer
* @return: a list of 10 new posts recently and sort by timeline
*/
public List<Tweet> getTimeline(int user_id) {
List<Tweet> result = new ArrayList<Tweet>();
List<Node> posts = userTweets.get(user_id);
if(posts != null && !posts.isEmpty()){
for(Node node: getLastTenTweet(posts)) {
result.add(node.tweet);
}
}
return result;
}
/*
* @param from_user_id: An integer
* @param to_user_id: An integer
* @return: nothing
*/
public void follow(int from_user_id, int to_user_id) {
fans.putIfAbsent(from_user_id, new HashSet<Integer>());
fans.get(from_user_id).add(to_user_id);
}
/*
* @param from_user_id: An integer
* @param to_user_id: An integer
* @return: nothing
*/
public void unfollow(int from_user_id, int to_user_id) {
if(fans.containsKey(from_user_id) && from_user_id != to_user_id) {
fans.get(from_user_id).remove(to_user_id);
}
}
}