当前位置:网站首页>golang刷leetcode 经典(3) 设计推特
golang刷leetcode 经典(3) 设计推特
2022-08-02 17:37:00 【用户9710217】
设计一个简化版的推特(Twitter),可以让用户实现发送推文,关注/取消关注其他用户,能够看见关注人(包括自己)的最近十条推文。你的设计需要支持以下的几个功能:
postTweet(userId, tweetId): 创建一条新的推文
getNewsFeed(userId): 检索最近的十条推文。每个推文都必须是由此用户关注的人或者是用户自己发出的。推文必须按照时间顺序由最近的开始排序。
follow(followerId, followeeId): 关注一个用户
unfollow(followerId, followeeId): 取消关注一个用户
示例:
Twitter twitter = new Twitter();
// 用户1发送了一条新推文 (用户id = 1, 推文id = 5).
twitter.postTweet(1, 5);
// 用户1的获取推文应当返回一个列表,其中包含一个id为5的推文.
twitter.getNewsFeed(1);
// 用户1关注了用户2.
twitter.follow(1, 2);
// 用户2发送了一个新推文 (推文id = 6).
twitter.postTweet(2, 6);
// 用户1的获取推文应当返回一个列表,其中包含两个推文,id分别为 -> [6, 5].
// 推文id6应当在推文id5之前,因为它是在5之后发送的.
twitter.getNewsFeed(1);
// 用户1取消关注了用户2.
twitter.unfollow(1, 2);
// 用户1的获取推文应当返回一个列表,其中包含一个id为5的推文.
// 因为用户1已经不再关注用户2.
twitter.getNewsFeed(1);解题思路:
动态的实现一般使用“拉模式”或者“推模式”,即用户可以看到的动态可以采用查询的时候直接计算(拉)也可以在用户的关注者发推的时候直接“推”到用户的动态列表。 本文使用“推模式”实现,如下是用到的几个数据结构: a)tweets用来存放用户发表的推文; b)feeds用来存放每个用户可以看到的动态; c)fans用来存放用户的粉丝(关注者)列表。 接下来看一下几个方法的实现逻辑: PostTweet:当用户发送一条推文时,tweets存一下该推文的id与时间,feeds把该动态append到末尾; GetNewsFeed:从末尾开始遍历feeds,返回最近的10条推文id; Follow:有用户a关注用户b,则把a放入b的fans列表,且把b的tweets推文并入a的feeds,因合并的两部分均是按时间升序排列的数组,所以避免使用常规排序算法,使用自写的merge函数可以加速合并; Unfollow:用用户a取消关注b,则将a从b的fans列表移除,还要从a的feeds中移除b的tweets。
注意几个坑
1,用户follow自己不合法
2,重复follow,unfollow
3,按时间戳排序,最好是id生成器,这里用unixnano简化,1000qps足够了
type Twitter struct {
users map[int]*User
tweets map[int]*Tweet
}
type Tweet struct{
ID int
UID int
time int64
}
type User struct{
ID int
followers map[int]*User
followees map[int]*User //关注的人,推模式用,这里没有使用
feed []*Tweet
tweets []*Tweet
}
func NewUser(userId int)*User{
return &User{
ID:userId,
followers:make(map[int]*User),
followees:make(map[int]*User),
}
}
/** Initialize your data structure here. */
func Constructor() Twitter {
return Twitter{
users:make( map[int]*User),
tweets:make( map[int]*Tweet),
}
}
/** Compose a new tweet. */
func (this *Twitter) PostTweet(userId int, tweetId int) {
u,ok:=this.users[userId]
if !ok{
u=NewUser(userId)
this.users[userId]=u
}
t:=Tweet{ID:tweetId,UID:userId,time: time.Now().UnixNano()}
this.tweets[tweetId]=&t
//fmt.Println(*this,len(this.users[userId].followers))
//push
u.feed=append(u.feed,&t)
u.tweets=append(u.tweets,&t)
for _,f:=range u.followers{
//fmt.Println(f)
if f!=nil{
f.feed=append(f.feed,&t)
}
}
//fmt.Println(u)
}
/** 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. */
func (this *Twitter) GetNewsFeed(userId int) []int {
var r []int
u,ok:=this.users[userId]
if !ok{
return r
}
for i:=0;i<len(u.feed);i++{
if i==10 {
break
}
r=append(r,u.feed[len(u.feed)-1-i].ID)
}
return r
}
/** Follower follows a followee. If the operation is invalid, it should be a no-op. */
func (this *Twitter) Follow(followerId int, followeeId int) {
if followerId==followeeId{
return
}
f1,ok:=this.users[followerId]
if !ok{
f1=NewUser(followerId)
//fmt.Println(1)
this.users[followerId]=f1
}
f2,ok:=this.users[followeeId]
if !ok{
f2=NewUser(followeeId)
// fmt.Println(2)
this.users[followeeId]=f2
}
if _,ok:=f2.followers[followerId];ok{
return
}
f2.followers[followerId]=f1
f1.feed=this.Merge(f1.feed,f2.tweets)
return
}
func (this *Twitter)Merge(f1,f2 []*Tweet)[]*Tweet{
if len(f1)==0{
return f2
}
if len(f2)==0{
return f1
}
var f []*Tweet
i:=0
j:=0
for i<len(f1) && j<len(f2){
if f1[i].time<f2[j].time{
f=append(f,f1[i])
i++
}else{
f=append(f,f2[j])
j++
}
}
for ;i<len(f1);i++{
f=append(f,f1[i])
}
for ;j<len(f2);j++{
f=append(f,f2[j])
}
return f
}
/** Follower unfollows a followee. If the operation is invalid, it should be a no-op. */
func (this *Twitter) Unfollow(followerId int, followeeId int) {
if followerId==followeeId{
return
}
f1,ok:=this.users[followerId]
if !ok{
return
}
f2,ok:=this.users[followeeId]
if !ok{
return
}
if _,ok=f2.followers[followerId];!ok{
return
}
delete(f2.followers,followerId)
var feedNew []*Tweet
for i:=range f1.feed{
//fmt.Println(f1.feed[i].UID,f2.ID)
if f1.feed[i].UID!=f2.ID{
feedNew=append(feedNew,f1.feed[i])
}
}
f1.feed=feedNew
}
/**
* Your Twitter object will be instantiated and called as such:
* obj := Constructor();
* obj.PostTweet(userId,tweetId);
* param_2 := obj.GetNewsFeed(userId);
* obj.Follow(followerId,followeeId);
* obj.Unfollow(followerId,followeeId);
*/边栏推荐
- 故障分析 | 一条 SELECT 语句跑崩了 MySQL ,怎么回事?
- 宝塔搭建实测-基于ThinkPHP5.1的wms进销存源码
- HDF驱动框架的API(2)
- 发挥云网融合优势,天翼云为政企铺设数字化转型跑道
- C# 术语
- MySQL基本操作和基于MySQL基本操作的综合实例项目
- 用函数递归的方法解决汉诺塔问题
- Gear 月度更新|6 月
- Since September, China has granted zero-tariff treatment to 98% of tax items from 16 countries including Togo
- 新特性解读 | MySQL 8.0 GIPK 不可见主键
猜你喜欢

小程序毕设作品之微信体育馆预约小程序毕业设计成品(6)开题答辩PPT

Redis的使用--集群模式

Security First: Tools You Need to Know to Implement DevSecOps Best Practices

Playing in the cloud | The key technology of Tianyi cloud object storage ZOS high availability is revealed

谁抢走了华大基因的生意?

LeetCode·76.最小覆盖子串·滑动窗口

MySQL基本操作和基于MySQL基本操作的综合实例项目

我用这一招让团队的开发效率提升了 100%!

MySQL基本语法

玩转云端 | 天翼云对象存储ZOS高可用的关键技术揭秘
随机推荐
宝塔搭建实测-基于ThinkPHP5.1的wms进销存源码
新特性解读 | MySQL 8.0 GIPK 不可见主键
golang源码分析(6):sync.Mutex sync.RWMutex
一文看懂推荐系统:概要01:推荐系统的基本概念
ECCV 2022 | 清华&腾讯AI Lab提出REALY:重新思考3D人脸重建的评估方法
9月起中国给予多哥等16国98%税目产品零关税待遇
二叉查找树的查找
发挥云网融合优势,天翼云为政企铺设数字化转型跑道
MySQL基本查询和运算符
Go编译原理系列6(类型检查)
Local broadcast MSE fragments mp4 service
MySQL基本语法
docker安装Oracle之后常用的一些命令
土巴兔IPO五次折戟,互联网家装未解“中介”之痛
Google Earth Engine APP—— 一个不用写代码可以直接下载相应区域的1984-2021年的GIF遥感影像动态图
Ubuntu系统下用docker安装oracle
0725-面试记录
小程序毕设作品之微信体育馆预约小程序毕业设计成品(5)任务书
织梦自定义表单添加全选和全不选功能按钮
2021年下半年软件设计师上午真题