当前位置:网站首页>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);
*/
边栏推荐
- 牛津硕士进碳圈,高瓴红杉经纬一起投了
- NeRF: The Secret of 3D Reconstruction Technology in the Popular Scientific Research Circle
- Redis的介绍和使用
- 故障分析 | 一条 SELECT 语句跑崩了 MySQL ,怎么回事?
- 透过案例看清API接口的作用——演示1688商品详情接口
- NeRF:火爆科研圈的三维重建技术大揭秘
- golang源码分析(2):Golang context 包
- 今年上半年,我国公路建设总体形势持续向好
- erp系统和wms系统有什么区别
- How Tencent architects explained: The principle of Redis high-performance communication (essential version)
猜你喜欢
分布式 | dble 启动的时候做了什么之配置检测
创新云集技术咖,工赋汇聚实战派:2022工赋开发者峰会
golang学习之七:并发编程基础(goroutine、channel、select)
牛津硕士进碳圈,高瓴红杉经纬一起投了
Taking advantage of cloud-network integration, e-Surfing Cloud has paved the way for digital transformation for government and enterprises
详细教学——1688关键词搜索API操作流程
Redis的使用--集群模式
来亲自手搭一个ResNet18网络
IReport常见问题及处理方法
mui中使用多级选择器实现省市区联动
随机推荐
MySQL索引
Arduino hardware programming introduction to language learning
golang源码阅读(11)GO中各个目录的功能
AI+医疗:使用神经网络进行医学影像识别分析
二舅“反转”了?
小程序毕设作品之微信体育馆预约小程序毕业设计成品(5)任务书
docker安装Oracle之后常用的一些命令
DeepMind 首席科学家 Oriol Vinyals 最新访谈:通用 AI 的未来是强交互式元学习
E-Surfing Cloud 4.0 Distributed Cloud Enables Digital Transformation of Thousands of Industries
新特性解读 | MySQL 8.0 GIPK 不可见主键
C语言中的一系列操作符
SQL 正则解析手机号码提供商
嵌入式Qt-做一个秒表
STL案例-招聘新员工
小程序毕设作品之微信体育馆预约小程序毕业设计成品(8)毕业设计论文模板
Gear 月度更新|6 月
Mini Program Graduation Works WeChat Gymnasium Reservation Mini Program Graduation Design Finished Product (8) Graduation Design Thesis Template
How Tencent architects explained: The principle of Redis high-performance communication (essential version)
golang源码分析(7):chan
Kubernetes:(五)Pod进阶(资源限制、健康检查)