LeetCode 第 262 题全解析:从 SQL 到 Swift 的数据分析实战

在这里插入图片描述
在这里插入图片描述

文章目录

    • 摘要
    • 描述
    • 题解答案(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 表,我们会:

  1. 解析数据结构

  2. 过滤掉被封禁的用户

  3. 筛选出符合时间条件的行程

  4. 分天统计总行程数和取消的行程数

  5. 最终计算每天的取消率并打印结果

代码示例(可运行 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 数据源,构建一个完整的监控看板。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

三生原理与现有密码学的核心区别?

AI辅助创作: 三生原理与现有密码学的核心区别 一、‌哲学基础与设计逻辑‌ ‌动态生成 vs 静态分析‌ 三生原理以“阴阳动态平衡”为核心,通过参数化生成(如素数构造中的阴阳元联动公式)模拟系统演化过程,而现有密码…

4.19-4.20学习总结 网络编程+反射+动态代理

网络编程: IPv6有2的128次方个ip。 端口号: 协议: UDP发送和接收消息: UDP的三种通信方式: 单播:一对一,一个发送端对应一个接收端 创建DatagramSocket对象 组播:一个发送端对应一…

Swiper、样式结构重用、GridGridItem

今日核心: 容器组件:Swiper、Grid\GridItem样式&结构重用:Builder、Extend、Styles 相关资源: 图片素材:📎day01.zip 1. Swiper 1.1. 适用场景 首先来看看 Swiper 在什么情况下会用到 链接 Swiper组件提供滑…

前沿分享|技术雷达202504月刊精华

本期雷达 ###技术部分 7. GraphRAG 试验 在上次关于 检索增强生成(RAG)的更新中,我们已经介绍了GraphRAG。它最初在微软的文章中被描述为一个两步的流程: (1)对文档进行分块,并使用基于大语言…

数据结构与算法-顺序表应用

一.通讯录的创建 首先我们要理解的是通讯录本身就是以顺序表为底层的 只不过顺序表中的数组,这里我们是用结构体来替代,用来存储用户的信息 由于是通讯录的本质就是顺序表,所以顺序表的任何方法它都能套用 Contact.h: #pragma once #def…

【C++】新手入门指南(下)

文章目录 前言 一、引用 1.引用的概念和定义 2.引用的特性 3.引用的使用 4.const引用 5.指针和引用的关系 二、内联函数 三、nullptr 总结 前言 这篇续上篇的内容新手入门指南(上),继续带大家学习新知识。如果你感兴趣欢迎订购本专栏。 一、…

uniapp-商城-33-shop 布局搜索页面以及u-search

shop页面上有一个搜索&#xff0c;可以进行商品搜索&#xff0c;这里我们先做一个页面布局&#xff0c;后面再来进行数据i联动。 1、shop页面的搜索 2、搜索的页面代码 <navigator class"searchView" url"/pagesub/pageshop/search/search"> …

SAP 采购订单如何防止开票数量 大于 收货数量呢

配置点如下&#xff1a; 事务码&#xff1a;OMRM&#xff0c;配置如下 当过账开票的数量 大于收货数量的时候会提示如下&#xff1a;

Kotlin 的 suspend 关键字

更多相关知识 Kotlin 的 suspend 关键字是 Kotlin 协程的核心组成部分&#xff0c;它用于标记一个函数可以被挂起&#xff08;暂停执行&#xff09;并在稍后恢复执行&#xff0c;而不会阻塞线程。 理解 suspend 的作用需要从以下几个方面入手&#xff1a; 1. 允许非阻塞的异步…

UDS诊断协议iso-14229 15765

Diagnostic request 形式多种: 1.SID+DID 2.SID+Sub-Func+DID 3.SID+Sub-Func SID占1个Byte,Sub-func占一个Byte,DID通常两个Byte eg.10 01 (SID+Sub-Func) 10 03 05 02 (SID+Sub-Func+DID) 22 02 00 (SID+DID) 肯定响应抑制位 抑制正响应信息除非是收到NRC 0x78的情况下 不…

记录一次使用面向对象的C语言封装步进电机驱动

简介 (2025/4/21) 本库对目前仅针对TB6600驱动下的42步进电机的基础功能进行了一定的封装, 也是我初次尝试以面向对象的思想去编写嵌入式代码, 和直流电机的驱动步骤相似在调用stepmotor_attach()函数和stepmotor_init()函数之后仅通过结构体数组stepm然后指定枚举变量中的id即…

[创业之路-376]:企业法务 - 创业,不同的企业形态,个人承担的风险、收益、税费、成本不同

在企业法务领域&#xff0c;创业时选择不同的企业形态&#xff0c;个人在风险承担、收益分配、税费负担及运营成本方面存在显著差异。以下从个人独资企业、合伙企业、有限责任公司、股份有限公司四种常见形态展开分析&#xff1a; 一、个人承担的风险 个人独资企业 风险类型&…

GNOME桌面隐藏回收站和分区

dconf-editor 搜索 trash&#xff0c;关闭 show-trash 搜索 volumes&#xff0c;关闭 show-volumns

准确--Tomcat更换证书

具体意思是&#xff1a; Starting Coyote HTTP/1.1 on http-8080: HTTP 连接器&#xff08;端口 8080&#xff09;启动成功了。严重: Failed to load keystore type PKCS12 with path conf/jlksearch.fzsmk.cn.pfx due to failed to decrypt safe contents entry: javax.crypt…

禁止ubuntu自动更新

由于ubuntu server和desktop版本都默认 启动了&#xff0c;自动更新内核的操作。这对于生 产环境来说是不友好的。容易导致亿赛通 无法启动 默认开启了内核自动更新所以我们关闭自 动内核更新。 1.禁止更新执行 sudo apt-mark hold linux-image-generic linux-headers-generic…

vue3 + element-plus中el-drawer抽屉滚动条回到顶部

el-drawer抽屉滚动条回到顶部 <script setup lang"ts" name"PerformanceLogQuery"> import { ref, nextTick } from "vue"; ...... // 详情 import { performanceLogQueryByIdService } from "/api/performanceLog"; const onD…

【重走C++学习之路】16、AVL树

目录 一、概念 二、AVL树的模拟实现 2.1 AVL树节点定义 2.2 AVL树的基本结构 2.3 AVL树的插入 1. 插入步骤 2. 调节平衡因子 3. 旋转处理 4. 开始插入 2.4 AVL树的查找 2.5 AVL树的删除 1. 删除步骤 2. 调节平衡因子 3. 旋转处理 4. 开始删除 结语 一、概念 …

char32_t、char16_t、wchar_t 用于 c++ 语言里存储 unicode 编码的字符,给出它们的具体定义

&#xff08;1&#xff09; #include <iostream> #include <string>int main() { std::u16string s u"C11 引入 char16_t"; // 定义 UTF-16 字符串for (char16_t c : s) // 遍历输出每个 char16_t 的值std::cout << std::hex << (…

redis数据类型-基数统计HyperLogLog

redis数据类型-基数统计HyperLogLog 文档 redis单机安装redis常用的五种数据类型redis数据类型-位图bitmap 说明 官网操作命令指南页面&#xff1a;https://redis.io/docs/latest/commands/?nameget&groupstringHyperLogLog介绍页面&#xff1a;https://redis.io/docs…

逻辑思维:从混沌到秩序的理性推演在软件开发中的应用

引言 在软件开发的过程中&#xff0c;逻辑思维就像是开发者的“GPS导航”&#xff0c;帮助我们从混沌的需求中找到清晰的解决方案。想象一下&#xff0c;如果没有逻辑思维&#xff0c;我们可能会在需求的海洋中迷失方向&#xff0c;最终写出一堆“看似聪明但毫无意义”的代码。…