Swift 實戰:實現一個簡化版的 Twitter(LeetCode 355)

在這里插入圖片描述
在這里插入圖片描述

文章目錄

    • 摘要
    • 描述
      • 示例
    • 解決答案
      • 設計思路
    • 題解代碼分析
    • 測試示例和結果
    • 時間復雜度
    • 空間復雜度
    • 總結

摘要

在社交媒體平臺里,推送機制是核心功能之一。比如你關注了某人,就希望在自己的時間線上能看到他們的最新消息,同時自己的消息也要能出現在別人的首頁。LeetCode 355 題——“設計推特”就把這個場景簡化成一個核心設計題。我們要實現一個小型 Twitter 系統,支持發推文、關注/取關用戶、獲取最新消息流。

這道題既考察數據結構的選擇,也鍛煉系統設計思維。接下來我會用 Swift 詳細實現,并提供一個可運行的 Demo 模塊,帶你一起拆解問題背后的思路。

描述

題目要求設計一個 Twitter 類,具備以下功能:

  1. postTweet(userId, tweetId)
    用戶 userId 發送一條推文,推文 ID 是 tweetId

  2. getNewsFeed(userId)
    返回用戶 userId 的新聞推送,內容包括:

    • 他自己發的推文
    • 他關注的人發的推文
    • 只取最近的 10 條,按時間順序由新到舊。
  3. follow(followerId, followeeId)
    用戶 followerId 關注用戶 followeeId

  4. unfollow(followerId, followeeId)
    用戶 followerId 取關用戶 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]]

解釋:

  • 用戶 1 發推文 [5]
  • 獲取新聞流 -> [5]
  • 用戶 1 關注用戶 2
  • 用戶 2 發推文 [6]
  • 用戶 1 獲取新聞流 -> [6, 5]
  • 用戶 1 取關用戶 2
  • 用戶 1 獲取新聞流 -> [5]

解決答案

設計思路

要滿足題目要求,我們需要以下幾個關鍵點:

  1. 存儲用戶發的推文
    使用字典 userTweets: [Int: [(Int, Int)]],鍵是 userId,值是推文 (時間戳, tweetId) 列表。

  2. 存儲用戶的關注關系
    使用字典 followees: [Int: Set<Int>],鍵是 userId,值是該用戶關注的用戶集合。

  3. 維護時間順序
    每次發推時記錄一個自增的全局時間戳 time,保證推文有先后順序。

  4. 獲取新聞流

    • 獲取當前用戶的推文 + 他關注的人的推文。
    • 合并這些推文,根據時間戳倒序排序,取前 10 條。

雖然這個實現不是最優(可以用堆優化),但對于題目給的約束(最多 3 * 10^4 次操作),完全夠用。

題解代碼分析

下面是 Swift 的完整實現代碼:

import Foundationclass Twitter {private var time = 0private var userTweets: [Int: [(Int, Int)]] = [:]  // userId -> [(time, tweetId)]private var followees: [Int: Set<Int>] = [:]       // userId -> Set of followeesinit() {}// 發推文func postTweet(_ userId: Int, _ tweetId: Int) {time += 1userTweets[userId, default: []].append((time, tweetId))}// 獲取新聞流(最近 10 條推文)func getNewsFeed(_ userId: Int) -> [Int] {var tweets: [(Int, Int)] = []// 自己的推文if let selfTweets = userTweets[userId] {tweets.append(contentsOf: selfTweets)}// 關注者的推文if let followeesSet = followees[userId] {for followee in followeesSet {if let followeeTweets = userTweets[followee] {tweets.append(contentsOf: followeeTweets)}}}// 按時間倒序排序,取前 10 條let sortedTweets = tweets.sorted { $0.0 > $1.0 }return sortedTweets.prefix(10).map { $0.1 }}// 關注func follow(_ followerId: Int, _ followeeId: Int) {guard followerId != followeeId else { return }  // 不能關注自己followees[followerId, default: []].insert(followeeId)}// 取關func unfollow(_ followerId: Int, _ followeeId: Int) {followees[followerId]?.remove(followeeId)}
}

測試示例和結果

我們寫一個測試函數,模擬題目里的操作:

func testTwitter() {let twitter = Twitter()twitter.postTweet(1, 5)print("News feed of user 1:", twitter.getNewsFeed(1)) // [5]twitter.follow(1, 2)twitter.postTweet(2, 6)print("News feed of user 1 after following 2:", twitter.getNewsFeed(1)) // [6, 5]twitter.unfollow(1, 2)print("News feed of user 1 after unfollowing 2:", twitter.getNewsFeed(1)) // [5]
}testTwitter()

運行結果:

News feed of user 1: [5]
News feed of user 1 after following 2: [6, 5]
News feed of user 1 after unfollowing 2: [5]

時間復雜度

  1. postTweet:O(1)
  2. follow / unfollow:O(1)
  3. getNewsFeed:O(n log n),其中 n 是自己和關注者的所有推文總數。因為要排序。

在題目約束下(調用次數最多 3 * 10^4),這個解法是可接受的。

空間復雜度

  • 存儲所有推文:O(totalTweets)
  • 存儲關注關系:O(totalUsers^2)(最壞情況所有人互相關注)

整體空間復雜度:O(totalTweets + totalFollows)。

總結

這道題考察的不是高深的算法,而是如何合理地組織數據結構

  • 推文需要保存時間順序,用全局自增計數器解決。
  • 用戶關系用字典 + 集合管理。
  • 獲取新聞流時把相關推文合并再排序。

這個設計在真實系統里當然不夠高效(Twitter 真實實現用的是復雜的分布式推送系統),但在算法題范圍內完全夠用。

關鍵 takeaway:

  • 拆分功能:發推、關注、取關、獲取新聞流,分別管理。
  • 數據結構選型:字典存推文和關系,數組/集合快速操作。
  • 排序保證時間順序:倒序取最近 10 條。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/919147.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/919147.shtml
英文地址,請注明出處:http://en.pswp.cn/news/919147.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

在瀏覽器端使用 xml2js 遇到的報錯及解決方法

在瀏覽器端使用 xml2js 遇到的報錯及解決方法 一、引言 在前端開發過程中&#xff0c;我們常常需要處理 XML 數據。xml2js 是一個非常流行的用于將 XML 轉換為 JavaScript 對象的庫。然而&#xff0c;當我們在瀏覽器端使用它時&#xff0c;可能會遇到一些問題。本文將介紹在瀏覽…

eChart餅環pie中間顯示總數_2個以上0值不擠掉

<!DOCTYPE html> <html> <head><meta charset"utf-8"><title>環餅圖顯示總數</title><script src"https://cdn.jsdelivr.net/npm/echarts5.4.3/dist/echarts.min.js"></script><style>#main { widt…

Ansible 核心功能進階:自動化任務的靈活控制與管理

一、管理 FACTS&#xff1a;獲取遠程主機的 “身份信息”FACTS 是 Ansible 自動收集的遠程主機詳細信息&#xff08;類似 “主機身份證”&#xff09;&#xff0c;包括主機名、IP、系統版本、硬件配置等。通過 FACTS 可以動態獲取主機信息&#xff0c;讓 Playbook 更靈活1. 查看…

gRPC網絡模型詳解

gRPC協議框架 TCP層&#xff1a;底層通信協議&#xff0c;基于TCP連接。 TLS層&#xff1a;該層是可選的&#xff0c;基于TLS加密通道。 HTTP2層&#xff1a;gRPC承載在HTTP2協議上&#xff0c;利用了HTTP2的雙向流、流控、頭部壓縮、單連接上的多 路復用請求等特性。 gRPC層…

[優選算法專題二滑動窗口——將x減到0的最小操作數]

題目鏈接 將x減到0的最小操作數 題目描述 題目解析 問題重述 給定一個整數數組 nums 和一個整數 x&#xff0c;每次只能從數組的左端或右端移除一個元素&#xff0c;并將該元素的值從 x 中減去。我們需要找到將 x 恰好減為 0 的最少操作次數&#xff0c;如果不可能則返回 -…

AOP配置類自動注入

本文主要探究AopAutoConfiguration配置類里面的bean怎么被自動裝配的。代碼如下&#xff1a;package com.example.springdemo.demos.a05;import com.example.springdemo.demos.a04.Bean1; import com.example.springdemo.demos.a04.Bean2; import com.example.springdemo.demos…

云計算-K8s 實戰:Pod、安全上下文、HPA 、CRD、網絡策略、親和性等功能配置實操指南

簡介 此次圍繞Kubernetes 日常管理中的核心場景,提供了從基礎到進階的實操配置指南。內容涵蓋 9 大關鍵知識點:從使用 nginx 鏡像創建 QoS 類為 Guaranteed 的 Pod,到為 Pod 配置安全上下文以指定運行用戶和組;從自定義 Student 資源類型(CRD),到配置 Sidecar 實現跨命…

嵌入式LINUX——————TCP并發服務器

一、服務器1.服務器分類單循環服務器&#xff1a;只能處理一個客戶端任務的服務器 并發服務器&#xff1a;可同時處理多個客戶端任務的服務器二、TCP并發服務器的構建1.如何構建&#xff1f; &#xff08;1&#xff09;多進程&#xff08;每一次創建都非常耗時耗空間&#…

論文潤色不能降低文章的重復率

最近大家問到多的&#xff0c;你們潤色好了重復率會不會就降低了。這事兒啊&#xff0c;得從好幾個方面去剖析&#xff0c;今天咱們就一塊兒來探個究竟。咱們先得清楚&#xff0c;重復率檢測工具一般會把內容標記成兩類&#xff1a;一是那些和其他文獻在文字表達上高度相似的部…

Python爬蟲實戰:構建alltheplaces平臺地理信息數據采集系統

1. 引言 1.1 研究背景與意義 在大數據與智慧城市建設的推動下,地理位置信息(如餐館、景點、公共設施等 POI 數據)已成為商業分析、城市規劃、公共服務優化的核心基礎數據。alltheplaces 作為全球領先的開放場所數據平臺,整合了來自多個數據源的標準化信息,涵蓋場所名稱、…

HTML第三次作業

抽獎項目代碼<!DOCTYPE html> <html lang"zh-CN"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>簡易抽獎轉盤</title><sty…

PyTorch 面試題及詳細答案120題(01-05)-- 基礎概念與安裝

《前后端面試題》專欄集合了前后端各個知識模塊的面試題&#xff0c;包括html&#xff0c;javascript&#xff0c;css&#xff0c;vue&#xff0c;react&#xff0c;java&#xff0c;Openlayers&#xff0c;leaflet&#xff0c;cesium&#xff0c;mapboxGL&#xff0c;threejs&…

云手機選哪個比較好用?

云手機作為基于云計算技術運行的一款虛擬手機&#xff0c;能夠幫助企業與個人用戶進行賬號多開和遠程訪問等多種功能&#xff0c;是手游玩家的首要選擇&#xff0c;能夠多開賬號掛機不卡頓&#xff0c;但是哪一款云手機更加流暢好用呢&#xff1f;對于熱衷于手游的玩家來說&…

[科研理論]無人機底層控制算法PID、LQR、MPC解析

文章目錄1. PX4飛控PID簡介1.1 位置控制器1.2 速度控制器1.3 加速度和yaw轉到姿態1.4 姿態控制器1.5 角速率控制器2. 線性二次型優化&#xff08;LQR&#xff09;控制3. 模型預測控制MPC/NMPC3.1 MPC3.2 NMPC1. PX4飛控PID簡介 相關鏈接&#xff1a;PX4官方中文文檔、PID概念(…

AI系統性思維復盤概述

核心價值&#xff1a;從“被動思考”到“主動進化”。 基于數據驅動、機器學習和知識圖譜的智能化組織學習系統&#xff0c;它將經驗積累從傳統的主觀性、碎片化模式轉變為客觀性、系統化的科學模式&#xff0c;最終實現從被動應對向主動預防、從經驗決策向數據決策、從個體智慧…

C++繼承(2)

2.基類和派生類間的轉換 ?public繼承的派?類對象可以賦值給基類的指針/基類的引?。這?有個形象的說法叫切?或者切 割。寓意把派?類中基類那部分切出來&#xff0c;基類指針或引?指向的是派?類中切出來的基類那部分。 ? 基類對象不能賦值給派?類對象。 ? 基類的指針或…

easya2a: 一鍵將 LangChain Agent 發布為 A2A 服務

easya2a: 一鍵將 LangChain Agent 發布為 A2A 服務 隨著 A2A (Agent-to-Agent) 協議的發布&#xff0c;相關的實踐項目也逐漸涌現。對于許多希望體驗 A2A 功能&#xff0c;但又擔心學習成本和開發時間的開發者來說&#xff0c;推薦使用 easya2a——一個可以快速、無縫地將現有 …

原學之設計模式- 設計模式來源

引言 各位旅行者們你們好&#xff0c;我是小森&#xff0c;首先我為啥是程序員。學了技術快六年了&#xff0c;但一直都是斷斷續續&#xff0c;本身自己的條件&#xff0c;從2021年11月份開始下載原神&#xff0c;總而言之不了解一些抽卡機制導致退了并且刪除了具體賬號打算重新…

有鹿機器人:AI技術如何重新定義「掃地」這件小事?

當掃地成為一門“技術活”掃地&#xff0c;可能是人類最古老的清潔行為之一。從掃帚到吸塵器&#xff0c;再到今天的無人駕駛清潔設備&#xff0c;我們一直在尋找更高效、更徹底的方式維護環境整潔。但有鹿機器人的出現&#xff0c;讓“掃地”這件事有了新的定義——它不再只是…

62.不同路徑

dp問題描述 62.不同路徑 確定本題的狀態表示 dp[i,j]表示的是從左上角走到這個位置的路徑條數 確定本題的狀態轉移方程 根據已知條件&#xff1a;dp[0,0]1&#xff0c;dp[0,1]1&#xff0c;dp[1,0]1 本題的狀態轉移方程是&#xff1a; dp[i,j]dp[i,j-1]dp[i-1,j] 填表求…