文章目錄
- 摘要
- 描述
- 題解答案(SQL)
- Swift 題解代碼分析
- 代碼示例(可運行 Demo)
- 示例測試及結果
- 時間復雜度分析
- 空間復雜度分析
- 總結
- 未來展望
摘要
在實際業務中,打車平臺要監控行程的取消率,及時識別服務質量的問題。這篇文章圍繞 LeetCode 第 262 題,帶大家用 Swift 和 SQL 解題,并深入聊聊如何結合用戶數據和行程數據去計算每天的取消率,尤其是只計算“非禁止用戶”的數據。咱們還會補充一個可運行的 Swift Demo 來模擬分析過程,并講解這類題目在數據分析、風控和運營決策中的價值。
描述
這個題目其實就是想讓我們統計每天的“非被封禁用戶”的取消率。用戶數據在一張表里,行程數據在另一張表里。我們要結合這兩張表篩選出符合條件的數據:
-
時間在 2013-10-01 到 2013-10-03 之間
-
用戶不能是被禁用的(
banned = No
) -
最終結果要按照天維度輸出,每天的取消率保留兩位小數
而且要注意,只有司機和乘客都不是禁止用戶的行程才參與計算。
題解答案(SQL)
雖然你要的是 Swift 題解,但這道題核心在于 SQL 聯表計算,我們先看 SQL 部分:
SELECT request_at AS Day,ROUND(SUM(CASE WHEN status IN ('cancelled_by_driver', 'cancelled_by_client') THEN 1ELSE 0END) * 1.0 / COUNT(*), 2) AS "Cancellation Rate"
FROM Trips t
JOIN Users c ON t.client_id = c.users_id AND c.banned = 'No'
JOIN Users d ON t.driver_id = d.users_id AND d.banned = 'No'
WHERE request_at BETWEEN '2013-10-01' AND '2013-10-03'
GROUP BY request_at;
Swift 題解代碼分析
我們用 Swift 來模擬整個 SQL 的流程。假設我們有兩個 JSON 數據源,分別對應 Trips
表和 Users
表,我們會:
-
解析數據結構
-
過濾掉被封禁的用戶
-
篩選出符合時間條件的行程
-
分天統計總行程數和取消的行程數
-
最終計算每天的取消率并打印結果
代碼示例(可運行 Demo)
import Foundationstruct Trip {let id: Intlet clientId: Intlet driverId: Intlet status: Stringlet requestAt: String
}struct User {let userId: Intlet banned: Stringlet role: String
}let users: [User] = [.init(userId: 1, banned: "No", role: "client"),.init(userId: 2, banned: "Yes", role: "client"),.init(userId: 3, banned: "No", role: "client"),.init(userId: 4, banned: "No", role: "client"),.init(userId: 10, banned: "No", role: "driver"),.init(userId: 11, banned: "No", role: "driver"),.init(userId: 12, banned: "No", role: "driver"),.init(userId: 13, banned: "No", role: "driver")
]let trips: [Trip] = [.init(id: 1, clientId: 1, driverId: 10, status: "completed", requestAt: "2013-10-01"),.init(id: 2, clientId: 2, driverId: 11, status: "cancelled_by_driver", requestAt: "2013-10-01"),.init(id: 3, clientId: 3, driverId: 12, status: "completed", requestAt: "2013-10-01"),.init(id: 4, clientId: 4, driverId: 13, status: "cancelled_by_client", requestAt: "2013-10-01"),.init(id: 5, clientId: 1, driverId: 10, status: "completed", requestAt: "2013-10-02"),.init(id: 6, clientId: 2, driverId: 11, status: "completed", requestAt: "2013-10-02"),.init(id: 7, clientId: 3, driverId: 12, status: "completed", requestAt: "2013-10-02"),.init(id: 8, clientId: 2, driverId: 12, status: "completed", requestAt: "2013-10-03"),.init(id: 9, clientId: 3, driverId: 10, status: "completed", requestAt: "2013-10-03"),.init(id: 10, clientId: 4, driverId: 13, status: "cancelled_by_driver", requestAt: "2013-10-03")
]let bannedUsers = Set(users.filter { $0.banned == "Yes" }.map { $0.userId })var result: [String: (cancelled: Int, total: Int)] = [:]for trip in trips {guard !bannedUsers.contains(trip.clientId),!bannedUsers.contains(trip.driverId),["2013-10-01", "2013-10-02", "2013-10-03"].contains(trip.requestAt)else { continue }let date = trip.requestAtvar entry = result[date] ?? (0, 0)if trip.status == "cancelled_by_driver" || trip.status == "cancelled_by_client" {entry.cancelled += 1}entry.total += 1result[date] = entry
}for (day, entry) in result {let rate = entry.total == 0 ? 0.0 : Double(entry.cancelled) / Double(entry.total)print("\(day): \(String(format: "%.2f", rate))")
}
示例測試及結果
運行上述 Swift 程序,將會輸出:
2013-10-01: 0.33
2013-10-02: 0.00
2013-10-03: 0.50
這與題目給出的標準結果一致。
時間復雜度分析
假設行程數為 n
,用戶數為 m
。
-
篩選禁止用戶集合:
O(m)
-
遍歷 trips 數據:
O(n)
-
最終輸出:
O(k)
,其中k
是天數,這里固定為 3 天
總體時間復雜度是:O(n + m)
空間復雜度分析
-
存儲禁止用戶集合:
O(m)
-
結果字典
result
:最多三天,常量空間
所以總空間復雜度是:O(m)
總結
這題表面是 SQL 題,其實是在考察我們對數據的過濾和聚合能力。無論是用 SQL 寫聯表查詢,還是用 Swift 做數據模擬,都離不開一個核心思想——干凈準確的數據處理。
這個例子在實際項目中特別常見,比如:
-
運營要知道每天的取消率趨勢
-
數據平臺需要過濾掉異常數據(比如封禁用戶)
-
數據分析師希望看到更精準的業務 KPI
未來展望
這類數據處理可以推廣到更多場景,比如:
-
留存率、點擊率、完成率的計算
-
實時監控系統中的數據聚合
-
用戶行為數據的質量控制
未來我們可以拓展這個 Demo,接入真實數據庫或 API 數據源,構建一個完整的監控看板。