#355. 设计推特 哈希map+优先队列+链表实现
2020/4/13每日一题打卡√ 难度:中等
题目描述
解题思路
这道题其实不难,思路都很简单,但是由于对数据结构不熟悉,一边写一边查那些数据结构的原理,用法还是花了好久。最后还卡在一个很低级的bug,找了好久才找到是哪里出问题了,着实还是太菜辽;这些数据结构是参考了别人的,效率好像还行的样子。
class Twitter {
private Map<Integer, Tweet> userTweet; //存储每个用户发送的所有推特,推特重新设计了一个类,方便操作,也符合设计的规范
private Map<Integer, Set<Integer>> userFollow; //存储每个用户关注的人,关注的人列表不需要维持有序,同时为了存取方便O(1)使用hashset,这样也可以避免插入重复的关注的人
private PriorityQueue<Tweet> maxHeap; //用优先队列来按时间顺序存储最近10条推特
private static int timestamp = 0; //时间戳,每发布一条时间+1
List<Integer> tweetList = new ArrayList<Integer>();
/** Initialize your data structure here. */
public Twitter() { //在这里面初始化数据结构
userTweet = new HashMap<>();
userFollow = new HashMap<>();
//优先队列,按时间排序
maxHeap = new PriorityQueue<>((o1, o2) -> -o1.time + o2.time); }
/** Compose a new tweet. */
//发送一条推特,没什么难度,如果有该用户的记录就直接在推特链前加一条
public void postTweet(int userId, int tweetId) {
Tweet newtw = new Tweet(userId, tweetId);
if(userTweet.containsKey(userId)) {
newtw.next = userTweet.get(userId);
}
else {
newtw.next = null;
}
userTweet.put(userId, newtw);
++timestamp;
}
/** 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. */
//经典的K路合并问题变形,使用优先队列可以简便完成
public List<Integer> getNewsFeed(int userId) {
maxHeap.clear(); //每次都要清空哦
Set<Integer> follow = userFollow.get(userId); //获取所有这个用户关注的人
if(follow == null) { //注意用户可能没有关注过人,如果不写这个会报空指针
follow = new HashSet<>();
}
follow.add(userId);
List<Integer> newsFeed = new ArrayList<Integer>(10);
Iterator<Integer> iterator = follow.iterator();
while(iterator.hasNext()){
Tweet ut = userTweet.get(iterator.next()); //用户关注的人的推特列表
int count = 0; //针对一个关注的人,最多只要比较前十条微博
while(ut != null && count < 10) {
maxHeap.offer(ut);
ut = ut.next;
++count;
}
}
int count = 0;
//取优先队列的前十个
while(!maxHeap.isEmpty() && count < 10) {
newsFeed.add(maxHeap.poll().tweetId);
count++;
}
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 (followerId == followeeId) { //可能出现自己关注自己的情况
return;
}
if(userFollow.containsKey(followerId)) {
userFollow.get(followerId).add(followeeId);
}
else {
Set<Integer> follow = new HashSet<>();
follow.add(followeeId);
userFollow.put(followerId,follow);
}
}
/** Follower unfollows a followee. If the operation is invalid, it should be a no-op. */
public void unfollow(int followerId, int followeeId) {
if (followerId == followeeId) { //可能出现自己关注自己的情况
return;
}
if(userFollow.containsKey(followerId)) {
Set<Integer> follow = userFollow.get(followerId);
follow.remove(followeeId);
}
}
class Tweet{ //推特类,表示一条推特,最新发送的放在前面,后发送的在后面
private int userId;
private int tweetId;
private int time;
public Tweet next;
public Tweet(int uid,int tid) {
this.userId = uid;
this.tweetId = tid;
this.time = timestamp;
this.next = null;
}
}
}
/** * 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); */
提交结果: