设计一个简化版的推特(Twitter),可以让用户实现发送推文,关注/取消关注其他用户,能够看见关注人(包括自己)的最近 10 条推文。
实现 Twitter 类:
Twitter() 初始化简易版推特对象 void postTweet(int userId, int tweetId) 根据给定的 tweetId 和 userId 创建一条新推文。每次调用此函数都会使用一个不同的 tweetId 。 List 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 的用户。
代码
var Twitter = function() {
this.userMap = new Map()
};
/**
* @param {number} userId
* @param {number} tweetId
* @return {void}
*/
Twitter.prototype.postTweet = function(userId, tweetId) {
if (!this.userMap.has(userId)) {
this.userMap.set(userId, new User(userId))
}
var u = this.userMap.get(userId)
u.post(tweetId)
};
/**
* @param {number} userId
* @return {number[]}
*/
Twitter.prototype.getNewsFeed = function(userId) {
var h = new Heap()
var res = [], candidates = [];
if (!this.userMap.has(userId)) {
return res
}
for (let ids of this.userMap.get(userId).followed) {
candidates = candidates.concat(this.userMap.get(ids).tweets)
}
h.heapify(candidates)
while (res.length < 10 && h.data.length) {
res.push(h.pop().tweetId)
}
return res
};
/**
* @param {number} followerId
* @param {number} followeeId
* @return {void}
*/
Twitter.prototype.follow = function(followerId, followeeId) {
if (!this.userMap.has(followerId)) {
this.userMap.set(followerId, new User(followerId))
}
if (!this.userMap.has(followeeId)) {
this.userMap.set(followeeId, new User(followeeId))
}
this.userMap.get(followerId).follow(followeeId)
};
/**
* @param {number} followerId
* @param {number} followeeId
* @return {void}
*/
Twitter.prototype.unfollow = function(followerId, followeeId) {
if (this.userMap.has(followerId)) {
this.userMap.get(followerId).unfollow(followeeId)
}
};
var timeStamp = 0
var Tweet = function (tweetId, timeStamp) {
this.tweetId = tweetId;
this.time = timeStamp
}
var User = function(userId) {
this.id = userId
this.followed = new Set();
this.tweets = [];
this.follow(userId)
}
User.prototype.follow = function(userId) {
this.followed.add(userId)
}
User.prototype.unfollow = function(userId) {
if (userId !== this.id) {
this.followed.delete(userId)
}
}
User.prototype.post = function(tweetId) {
var tweet = new Tweet(tweetId, timeStamp)
timeStamp++
this.tweets.unshift(tweet)
}
class Heap {
constructor() {
this.data = [];
}
heapify(data) {
this.data = data
if (this.size() < 2) return
for (let i = 1; i < this.size(); i++) {
this.bubbleUp(i)
}
}
swap(i, j) {
[this.data[i], this.data[j]] = [this.data[j], this.data[i]]
}
compartor(i, j) {
return this.data[i]['time'] - this.data[j]['time'];
}
size() {
return this.data.length;
}
peek() {
if (!this.size()) return null;
return this.data[0]
}
offer(val) {
this.data.push(val);
this.bubbleUp(this.data.length-1);
}
pop() {
if (!this.size()) return null;
let res = this.data[0];
if (this.size() > 1) {
this.data[0] = this.data.pop();
this.bubbleDown(0);
} else {
this.data.pop();
}
return res;
}
bubbleUp(index) {
while(index) {
let parent = (index - 1) >> 1;
if (this.compartor(index, parent) > 0) {
this.swap(index, parent);
index = parent;
} else {
break;
}
}
}
bubbleDown(index, key) {
let last = this.data.length - 1;
while(index < last) {
let temp = index, left = index * 2 + 1, right = index * 2 + 2;
if (left <= last && this.compartor(left, temp) > 0) {
temp = left;
}
if (right <= last && this.compartor(right, temp) > 0) {
temp = right;
}
if (temp == index) break;
this.swap(temp, index);
index = temp;
}
}
}
/**
* Your Twitter object will be instantiated and called as such:
* var obj = new Twitter()
* obj.postTweet(userId,tweetId)
* var param_2 = obj.getNewsFeed(userId)
* obj.follow(followerId,followeeId)
* obj.unfollow(followerId,followeeId)
*/