LeetCode题练习与总结:设计推特--355

一、题目描述

设计一个简化版的推特(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 <= 500
  • 0 <= tweetId <= 10^4
  • 所有推特的 ID 都互不相同
  • postTweetgetNewsFeedfollow 和 unfollow 方法最多调用 3 * 10^4 次

二、解题思路

  1. 使用一个数据结构来存储推文,可以使用列表或链表,列表中的每个元素代表一条推文,包含推文ID和用户ID。考虑到需要频繁地在头部插入新推文,使用链表结构更合适。

  2. 使用一个哈希表来存储用户关注关系,键为用户ID,值为该用户关注的所有用户ID集合。

  3. postTweet 方法:在推文链表的头部插入一条新推文。

  4. getNewsFeed 方法:遍历推文链表,找出当前用户和其关注用户的推文,按时间顺序排序,取前10条推文。

  5. follow 方法:在关注关系的哈希表中,将关注者ID添加到被关注者的关注者集合中。

  6. unfollow 方法:在关注关系的哈希表中,将关注者ID从被关注者的关注者集合中移除。

三、具体代码

import java.util.*;

public class Twitter {

    private static class Tweet {
        int time;
        int tweetId;
        Tweet next;

        public Tweet(int time, int tweetId) {
            this.time = time;
            this.tweetId = tweetId;
            this.next = null;
        }
    }

    private Map<Integer, Set<Integer>> follows;
    private Map<Integer, Tweet> tweets;
    private int timeStamp;

    public Twitter() {
        follows = new HashMap<>();
        tweets = new HashMap<>();
        timeStamp = 0;
    }

    public void postTweet(int userId, int tweetId) {
        Tweet newTweet = new Tweet(timeStamp++, tweetId);
        newTweet.next = tweets.get(userId);
        tweets.put(userId, newTweet);
    }

    public List<Integer> getNewsFeed(int userId) {
        List<Tweet> list = new ArrayList<>();
        // 添加当前用户的推文
        if (tweets.containsKey(userId)) {
            list.add(tweets.get(userId));
        }
        // 添加关注用户的推文
        if (follows.containsKey(userId)) {
            for (int followeeId : follows.get(userId)) {
                if (tweets.containsKey(followeeId)) {
                    list.add(tweets.get(followeeId));
                }
            }
        }
        // 按时间排序
        list.sort((a, b) -> b.time - a.time);
        List<Integer> res = new ArrayList<>();
        for (Tweet tweet : list) {
            while (tweet != null && res.size() < 10) {
                res.add(tweet.tweetId);
                tweet = tweet.next;
            }
        }
        return res;
    }

    public void follow(int followerId, int followeeId) {
        follows.computeIfAbsent(followerId, k -> new HashSet<>()).add(followeeId);
    }

    public void unfollow(int followerId, int followeeId) {
        if (follows.containsKey(followerId)) {
            follows.get(followerId).remove(followeeId);
        }
    }
}

四、时间复杂度和空间复杂度

1. 时间复杂度
  • Twitter 构造函数:

    • 初始化数据结构,时间复杂度为O(1)。
  • postTweet 方法:

    • 每次调用时,直接在哈希表中插入新的推文节点,时间复杂度为O(1)。
  • getNewsFeed 方法:

    • 遍历所有关注者的推文,最坏情况下,如果用户关注了所有其他用户,时间复杂度为O(N),其中N是用户数量。
    • 将所有推文节点加入列表,时间复杂度为O(N)。
    • 对推文列表进行排序,时间复杂度为O(MlogM),其中M是推文总数。
    • 遍历排序后的推文列表以获取前10条推文,最坏情况下时间复杂度为O(M)。
    • 综合起来,getNewsFeed的时间复杂度为O(N + MlogM + M)。
  • follow 方法:

    • 在哈希表中添加关注关系,时间复杂度为O(1)。
  • unfollow 方法:

    • 在哈希表中移除关注关系,时间复杂度为O(1)。
2. 空间复杂度
  • Twitter 构造函数:

    • 初始化了两个哈希表和一个整数,空间复杂度为O(N),其中N是用户数量。
  • postTweet 方法:

    • 每次调用时,创建一个新的推文节点,空间复杂度为O(1)。
  • getNewsFeed 方法:

    • 创建了一个推文列表,最坏情况下,列表的大小为所有用户推文的总数M,空间复杂度为O(M)。
  • follow 方法:

    • 在哈希表中添加关注关系,空间复杂度为O(1)。
  • unfollow 方法:

    • 移除哈希表中的关注关系,空间复杂度为O(1)。

总体空间复杂度:

  • follows 哈希表存储了所有用户的关注关系,空间复杂度为O(N^2)。
  • tweets 哈希表存储了所有用户的推文,空间复杂度为O(M)。
  • 因此,总体空间复杂度为O(N^2 + M)。

综上所述,该Twitter类的时间复杂度和空间复杂度分别为O(N + MlogM + M)和O(N^2 + M)。

五、总结知识点

  • 静态内部类

    • Tweet 类被定义为 Twitter 类的静态内部类,用于表示一条推文,包含时间戳、推文ID和指向下一条推文的引用。
  • 数据结构

    • 使用了 HashMap 和 HashSet 来存储用户关注关系和用户的推文链表。
    • Tweet 类形成了一个单向链表,用于存储用户的所有推文。
  • 时间戳

    • 使用一个整数 timeStamp 作为全局时间戳,每次发推时递增,用于确定推文的顺序。
  • 构造函数

    • Twitter 类的构造函数初始化了两个哈希表 follows 和 tweets,以及时间戳 timeStamp
  • 方法重载

    • postTweetgetNewsFeedfollow 和 unfollow 方法是 Twitter 类的成员方法,用于实现推文发布、获取新闻源、关注和取消关注的功能。
  • 链表操作

    • 在 postTweet 方法中,通过修改链表的头节点来添加新的推文。
    • 在 getNewsFeed 方法中,通过遍历链表来收集推文ID。
  • 集合操作

    • 使用 HashMap 的 computeIfAbsent 方法来安全地添加关注关系,避免空指针异常。
    • 使用 HashSet 的 add 和 remove 方法来管理关注列表。
  • 排序算法

    • 在 getNewsFeed 方法中,使用 List 的 sort 方法结合自定义比较器来对推文按时间戳降序排序。
  • 迭代器使用

    • 在 getNewsFeed 方法中,使用迭代器遍历推文链表,并收集推文ID。
  • 条件判断

    • 在 getNewsFeedfollow 和 unfollow 方法中,使用了条件判断来处理边界情况和异常情况。

以上就是解决这个问题的详细步骤,希望能够为各位提供启发和帮助。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/904879.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

有序序列合并(c语言)

代码实例 int main() {int n 0;int m 0;scanf("%d %d", &n, &m);//n输入第一个升序数组中的元素个数//m输入第二个升序数组中的元素个数//创建数组//arr1为n对应的数组int arr1[1000];//arr2为m对应的数组int arr2[1000];//arr3为数组1与数组2结合后的数组…

Java审计对比工具JaVers使用

最近有个需求&#xff0c;需要将页面的内容生成excel或者word文档&#xff0c;而且每次的修改都需要生成新的版本&#xff0c;同时需要记录每次修改变化的内容。我们会把每次的修改的内容提交赋值给一个java对象&#xff0c;同时存储到数据库一条新数据&#xff0c;对应数据表一…

知识图谱:连接实体与关系的语义网络

知识图谱作为人工智能领域的核心技术之一&#xff0c;是一种通过三元组&#xff08;实体关系属性&#xff09;形式&#xff0c;结构化表达实体间关系的语义网络。这种网络不仅嵌入了丰富的语义和逻辑&#xff0c;还遵循一定的规则&#xff0c;使其成为人类进行推理、预测和分类…

免费PDF页面提取小工具

下载地址 https://download.csdn.net/download/woshichenpi/89922797 使用说明&#xff1a;PDF页面提取工具 1. 启动应用程序 双击程序的启动图标或者通过命令行运行程序。 2. 选择PDF文件 在应用程序窗口中找到“选择PDF”按钮并点击它。在弹出的文件选择对话框中&#x…

法律智能助手:开源NLP系统助力法律文件高效审查与检索

一、系统概述 思通数科AI平台是一款融合了自然语言处理和多标签分类技术的开源智能文档分类工具&#xff0c;特别适用于法律行业。平台采用深度学习的BERT模型来进行特征提取与关系抽取&#xff0c;实现了精准的文档分类和检索。用户可以在线训练和标注数据&#xff0c;使系统…

-XSS-

链接 https://github.com/do0dl3/xss-labs 搭建过程非常容易的 搭建好之后&#xff0c;就可以点击图片开始闯关了 第一关--JS弹窗函数alert() 显示payload的长度是4 level1.php?nametest level1.php?nametest1 发现只要改变name的值就显示什么在页面上 没有什么过滤的 …

Python | Leetcode Python题解之第522题最长特殊序列II

题目&#xff1a; 题解&#xff1a; class Solution:def findLUSlength(self, strs: List[str]) -> int:def is_subseq(s: str, t: str) -> bool:pt_s pt_t 0while pt_s < len(s) and pt_t < len(t):if s[pt_s] t[pt_t]:pt_s 1pt_t 1return pt_s len(s)ans …

VBto Converter是一款功能强大的工具,可让您快速轻松地将Microsoft Visual Basic 6.0项目转换

VBto Converter是一款功能强大的工具&#xff0c;可让您快速轻松地将Microsoft Visual Basic 6.0项目转换 1、简介2、官方网站3、本站下载&#xff08;已汉化&#xff09; 1、简介 VBto Converter V2.90 版本&#xff0c;是一款功能强大的工具&#xff0c;可让您快速轻松地将M…

勒索软件通过易受攻击的 Cyber​​Panel 实例攻击网络托管服务器

一个威胁行为者&#xff08;或可能多个&#xff09;使用 PSAUX 和其他勒索软件攻击了大约 22,000 个易受攻击的 Cyber​​Panel 实例以及运行该实例的服务器上的加密文件。 PSAUX 赎金记录&#xff08;来源&#xff1a;LeakIX&#xff09; Cyber​​Panel 漏洞 Cyber​​Pane…

创新业态下金融头部机构在 FICC 平台建设上的思考与实践

近年来&#xff0c;FICC 投资交易呈现活跃多元态势&#xff0c;创新转型稳步推进。FICC 平台电子化方兴未艾&#xff0c;是机构提升服务效率和质量的一大着力点。因此&#xff0c;在 FICC 平台建设上&#xff0c;许多机构都进行了深入研究&#xff0c;积累了丰富的实践经验。 …

RedisIO多路复用

一、多路复用要解决的问题: 并发多客户端连接&#xff0c;在多路复用之前的处理方案是同步阻塞网络IO模型&#xff0c;这种模型的特点就是用一个进程来处理一个网络连接。优点在于比较简单&#xff0c;缺点在于性能较差&#xff0c;每个用户请求到来都得占用一个进程来处理&am…

XML解析小坑记录[正则表达式解析]

一、问题描述 在做 SSO 单点登录时( 认证中为CAS服务对接 )。在完成对用户ticket票根校验后&#xff0c;返回了用户信息有关 XML 数据片段&#xff0c;例如下&#xff1a; <cas:serviceResponse xmlns:cas"http://www.xxx.xx/xx/cas"><cas:authentication…

人工智能与伦理:我们应该如何平衡科技与人性?

内容概要 在这个瞬息万变的时代&#xff0c;人工智能的迅猛发展让我们面对前所未有的伦理困境。科技进步带来了便利&#xff0c;但同时也亟需我们反思如何对待人性。尤其是在实现算法透明性时&#xff0c;我们要确保每一个决策背后都能被理解与追溯&#xff0c;这不仅是对技术…

electron展示下载进度条

我们使用electron下载文件时&#xff0c;会发现不像浏览器一样会有地方展示下载进度&#xff0c;这导致下载一些大文件时不知道下载进度到哪里了 下面我们通过electron提供的will-download监听和element-plus中的ElNotification和ElProgress组件实现这一功能 实现逻辑 触发…

【算法】(Python)回溯算法

回溯算法&#xff1a; 回溯算法是一种算法思想。采用“深度优先搜索&#xff08;dfs&#xff0c;depth first search&#xff09;”。采用“尝试”和“回溯”的策略。尝试搜索所有可能的解决方案&#xff0c;遇到不满足条件的撤销选择、回退到回溯点&#xff08;满足回溯条件的…

音视频入门基础:FLV专题(18)——Audio Tag简介

一、引言 根据《video_file_format_spec_v10_1.pdf》第75页&#xff0c;如果某个Tag的Tag header中的TagType值为8&#xff0c;表示该Tag为Audio Tag&#xff1a; 这时StreamID之后紧接着的就是AudioTagHeader&#xff0c;也就是说这时Tag header之后的就是AudioTagHeader&…

探索Python终端美化的终极利器:Rich库

文章目录 &#x1f680; 探索Python终端美化的终极利器&#xff1a;Rich库第一部分&#xff1a;背景介绍第二部分&#xff1a;Rich库是什么&#xff1f;第三部分&#xff1a;如何安装Rich库&#xff1f;第四部分&#xff1a;Rich库的简单函数使用方法第五部分&#xff1a;结合场…

【Java笔记】1-JDK/JRE/JVM是个啥?

JDK、JRE、JVM可以说是入门必须了解的三个词汇 先说全称 JDK&#xff1a;Java Development Kit&#xff0c;Java开发工具包 JRE&#xff1a;Java Runtime Environment&#xff0c;Java运行环境 JVM&#xff1a;Java Virtual Machine&#xff0c;Java虚拟机 再说关系 JVM⊆J…

视觉目标检测标注xml格式文件解析可视化 - python 实现

视觉目标检测任务&#xff0c;通常用 labelimage标注&#xff0c;对应的标注文件为xml。 该示例来源于开源项目&#xff1a;https://gitcode.com/DataBall/DataBall-detections-100s/overview 读取 xml 标注文件&#xff0c;并进行可视化示例如下&#xff1a; #-*-coding:ut…

金和OA-C6 ApproveRemindSetExec.aspx XXE漏洞复现(CNVD-2024-40568)

0x01 产品描述&#xff1a; 金和C6协同管理平台是以"精确管理思想"为灵魂&#xff0c;围绕“企业协同四层次理论”模型&#xff0c;并紧紧抓住现代企业管理的六个核心要素&#xff1a;文化 Culture、 沟通Communication 、 协作Collaboration 、创新 Creation、 控制…