题目描述
设计一个简化版的推特(Twitter),可以让用户实现发送推文,关注/取消关注其他用户,能够看见关注人(包括自己)的最近 10 条推文。
实现 Twitter 类:
Twitter()初始化简易版推特对象void postTweet(int userId, int tweetId)根据给定的tweetId和userId创建一条新推文。每次调用此函数都会使用一个不同的tweetId。List<Integer> getNewsFeed(int userId)检索当前用户新闻推送中最近10条推文的 ID 。新闻推送中的每一项都必须是由用户关注的人或者是用户自己发布的推文。推文必须 按照时间顺序由最近到最远排序 。void follow(int followerId, int followeeId)ID 为followerId的用户开始关注 ID 为followeeId的用户。void unfollow(int followerId, int followeeId)ID 为followerId的用户不再关注 ID 为followeeId的用户。
示例:
输入
["Twitter", "postTweet", "getNewsFeed", "follow", "postTweet", "getNewsFeed", "unfollow", "getNewsFeed"]
[[], [1, 5], [1], [1, 2], [2, 6], [1], [1, 2], [1]]
输出
[null, null, [5], null, null, [6, 5], null, [5]]
解释
Twitter twitter = new Twitter();
twitter.postTweet(1, 5); // 用户 1 发送了一条新推文 (用户 id = 1, 推文 id = 5)
twitter.getNewsFeed(1); // 用户 1 的获取推文应当返回一个列表,其中包含一个 id 为 5 的推文
twitter.follow(1, 2); // 用户 1 关注了用户 2
twitter.postTweet(2, 6); // 用户 2 发送了一个新推文 (推文 id = 6)
twitter.getNewsFeed(1); // 用户 1 的获取推文应当返回一个列表,其中包含两个推文,id 分别为 -> [6, 5] 。推文 id 6 应当在推文 id 5 之前,因为它是在 5 之后发送的
twitter.unfollow(1, 2); // 用户 1 取消关注了用户 2
twitter.getNewsFeed(1); // 用户 1 获取推文应当返回一个列表,其中包含一个 id 为 5 的推文。因为用户 1 已经不再关注用户 2
提示:
1 <= userId, followerId, followeeId <= 5000 <= tweetId <= 104- 所有推特的 ID 都互不相同
postTweet、getNewsFeed、follow和unfollow方法最多调用3 * 104次
本题中要获取用户的推文列表还有对用户进行关注和取关的操作,所以在 Twitter 类中肯定要维护一个用户列表
除此之外,因为要对推文进行时间由近到远排序,所以需要有一个属性标识每条推文的先后顺序,这里可以在 Twitter 类中维护一个自增的 id,每次有新的推文发送,将类中的 id 赋值给推文 id,然后将类中的 id 加 1
那每一个用户对象中,应该有两个属性
一个 list 属性保存该用户最近发的 10 条推文(因为获取推文只需要获取最近 10 条即可,所以无需保留更早的推文)
以及一个 follows 属性保存当前用户关注的用户列表
获取推文的时候,需要获取当前用户自己发送的最近十条推文以及关注的人的最近十条推文,将这些推文按照时间顺序由近到远排序,前十条就是 getNewsFeed 方法需要的结果
关注操作就是将被关注者 id 添加到关注者 follows 列表中
取关操作就是将被关注者 id 从关注者 follows 列表中删除
代码实现
var Twitter = function() {
// 自增id
this.id = 0;
// 用户列表
this.users = {};
};
/**
* @param {number} userId
* @param {number} tweetId
* @return {void}
*/
Twitter.prototype.postTweet = function(userId, tweetId) {
// 如果当前用户数据没有初始化,进行初始化
if(!this.users[userId]) this.users[userId] = {
list:[],
follows:new Set()
}
// 将当前推文存入用户推文列表中
this.users[userId].list.push({id:this.id++,tweetId})
// 维护用户推文列表只保存最近的十条推文
if(this.users[userId].list.length>10) this.users[userId].list.shift();
};
/**
* @param {number} userId
* @return {number[]}
*/
Twitter.prototype.getNewsFeed = function(userId) {
// 因为会在用户发送推文或者用户关注其他人的时候初始化用户数据
// 所以此时如果用户数据未初始化,则说明用户没有发送过推文,也没有关注过其他用户,返回 []
if(!this.users[userId]) return [];
// 收集当前用户最近十条推文及其关注的人的最近十条推文的合集
let arr = this.users[userId].list;
this.users[userId].follows.forEach(item => {
if(this.users[item]){
arr = [...arr,...this.users[item].list]
}
})
// 按照时间顺序从近到远排序
arr.sort((a,b) => b.id-a.id);
// 获取最近的十条推文的id
const res = [];
for(let i = 0;i<Math.min(arr.length,10);i++){
res.push(arr[i].tweetId)
}
return res;
};
/**
* @param {number} followerId
* @param {number} followeeId
* @return {void}
*/
Twitter.prototype.follow = function(followerId, followeeId) {
// 如果当前关注者数据未初始化,则进行初始化
if(!this.users[followerId]) this.users[followerId] = {
list:[],
follows:new Set()
}
// 将被关注者用户ID添加到关注者关注列表中
this.users[followerId].follows.add(followeeId)
};
/**
* @param {number} followerId
* @param {number} followeeId
* @return {void}
*/
Twitter.prototype.unfollow = function(followerId, followeeId) {
// 将被关注者用户ID从关注者关注列表中删除
this.users[followerId].follows.delete(followeeId)
};
至此我们就完成了 leetcode-355-设计推特
如有任何问题或建议,欢迎留言讨论!