每日算法 -【Swift 算法】三数之和

Swift|三数之和(3Sum)详细题解 + 注释 + 拓展(LeetCode 15)

✨题目描述

给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a, b, c,使得 a + b + c = 0。请你找出所有和为 0 且不重复的三元组。

注意:答案中不能包含重复的三元组。


🧠解题思路

本题是 LeetCode 中非常经典的“双指针”+“去重”问题,属于中等难度。

✅ 步骤如下:

  1. 对数组进行排序:便于后续去重处理和双指针的使用。
  2. 固定一个数 nums[i]:枚举 i,并为其设置两个指针 left(i+1)和 right(nums.count - 1)。
  3. 使用双指针向中间靠拢,判断三数之和是否为 0。
  4. 去重操作
    • i 进行去重,跳过与前一个数相同的情况。
    • leftright 也要去重,防止重复三元组。

🧾 Swift 代码实现(含详细注释)

func threeSum(_ nums: [Int]) -> [[Int]] {let nums = nums.sorted()  // 排序是关键,便于去重和双指针var result: [[Int]] = []for i in 0..<nums.count - 2 {// 如果当前数字和前一个数字相同,跳过,避免重复三元组if i > 0 && nums[i] == nums[i - 1] {continue}var left = i + 1var right = nums.count - 1while left < right {let sum = nums[i] + nums[left] + nums[right]if sum == 0 {// 找到一个有效三元组result.append([nums[i], nums[left], nums[right]])// 去重:移动 left 指针跳过相同的数while left < right && nums[left] == nums[left + 1] {left += 1}// 去重:移动 right 指针跳过相同的数while left < right && nums[right] == nums[right - 1] {right -= 1}left += 1right -= 1} else if sum < 0 {// 总和偏小,左指针右移以增大总和left += 1} else {// 总和偏大,右指针左移以减小总和right -= 1}}}return result
}

⏱️时间复杂度分析

步骤复杂度
排序O(nlogn)
遍历 + 双指针查找O(n^2)
总体时间复杂度O(n²)
  • n 是数组的长度。
  • 最坏情况下,每个元素都要与后面的所有元素进行组合查找。

🧠空间复杂度

  • 使用了常数级别的辅助空间(除了结果数组):O(1)
  • 如果考虑返回结果的空间,那么是 O(k),其中 k 为结果中三元组的个数。

🔍输入输出示例

let nums = [-1, 0, 1, 2, -1, -4]
print(threeSum(nums)) 
// 输出: [[-1, -1, 2], [-1, 0, 1]]

🧱边界情况说明

输入输出说明
[][]空数组
[0, 0, 0][[0,0,0]]需要处理重复值
[1, 2, -2, -1][]没有满足条件的组合

🧩拓展与优化

  1. 如果要求和为 target 而非 0

    • 将判断条件 sum == 0 改为 sum == target 即可。
    • 本题可以推广为 kSum 问题(如 Two Sum、Four Sum)。
  2. 去重逻辑处理建议封装为函数

    • 提高代码可读性与复用性。
  3. Swift 中使用 Set 存储结果避免重复

    • 如果输入较多或存在重复项较多,可以考虑用 Set<[Int]> 先去重再转成 [[Int]]

🏁总结

  • 本题考察的是数组排序 + 双指针技巧。
  • 核心是合理处理重复元素,避免重复解。
  • 时间复杂度为 O(n²),在面试中属于经典问题,建议掌握。

如果你觉得有用,欢迎点赞、评论支持我继续更新 💪
你也可以在评论区分享你遇到的变体,我来帮你一起解答!

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

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

相关文章

服务器磁盘空间被Docker容器日志占满处理方法

事发场景&#xff1a; 原本正常的服务停止运行了&#xff0c;查看时MQTT服务链接失败&#xff0c;查看对应的容器服务发现是EMQX镜像停止运行了&#xff0c;重启也是也报错无法正常运行&#xff0c;报错如下图&#xff1a; 报错日志中连续出现两个"no space left on devi…

令牌桶 滑动窗口->限流 分布式信号量->限并发的原理 lua脚本分析介绍

文章目录 前言限流限制并发的实际理解限流令牌桶代码实现结果分析令牌桶lua的模拟实现原理总结&#xff1a; 滑动窗口代码实现结果分析lua脚本原理解析 限并发分布式信号量代码实现结果分析lua脚本实现原理 双注解去实现限流 并发结果分析&#xff1a; 实际业务去理解体会统一注…

基于uniapp+WebSocket实现聊天对话、消息监听、消息推送、聊天室等功能,多端兼容

基于 ​UniApp + WebSocket​实现多端兼容的实时通讯系统,涵盖WebSocket连接建立、消息收发机制、多端兼容性配置、消息实时监听等功能,适配​微信小程序、H5、Android、iOS等终端 目录 技术选型分析WebSocket协议优势UniApp跨平台特性WebSocket 基础实现连接管理消息收发连接…

Linux中shell编程表达式和数组讲解

一、表达式 1.1 测试表达式 样式1: test 条件表达式 样式2: [ 条件表达式 ] 注意&#xff1a;以上两种方法的作用完全一样&#xff0c;后者为常用。但后者需要注意方括号[、]与条件表达式之间至少有一个空格。test跟 [] 的意思一样条件成立&#xff0c;状态返回值是0条件不成…

深入了解JavaScript当中如何确定值的类型

JavaScript是一种弱类型语言&#xff0c;当你给一个变量赋了一个值&#xff0c;该值是什么类型的&#xff0c;那么该变量就是什么类型的&#xff0c;并且你还可以给一个变量赋多种类型的值&#xff0c;也不会报错&#xff0c;这就是JavaScript的内部机制所决定的&#xff0c;那…

【p2p、分布式,区块链笔记 MESH】Bluetooth蓝牙通信拓扑与操作 BR/EDR(经典蓝牙)和 BLE

目录 1. BR/EDR&#xff08;经典蓝牙&#xff09;网络结构微微网&#xff08;Piconet&#xff09;散射网&#xff08;Scatternet&#xff09;蓝牙 BR/EDR 拓扑结构示意图 2. BLE&#xff08;低功耗蓝牙&#xff09;网络结构广播器与观察者&#xff08;Broadcaster and Observer…

C++虚函数表(虚表Virtual Table,简称vtable、VFT)(编译器为支持运行时多态(动态绑定)而自动生成的一种内部数据结构)虚函数指针vptr

文章目录 **1. 虚函数表的核心概念**- **虚函数表&#xff08;vtable&#xff09;**&#xff1a;- **虚函数指针&#xff08;vptr&#xff09;**&#xff1a; **2. 虚函数表的生成与工作流程****生成时机**- **当一个类中至少有一个虚函数时**&#xff0c;编译器会为该类生成一…

使用Python和TensorFlow实现图像分类

最近研学过程中发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击链接跳转到网站人工智能及编程语言学习教程。读者们可以通过里面的文章详细了解一下人工智能及其编程等教程和学习方法。下面开始对正文内容的…

Unity UI 性能优化--Sprite 篇

&#x1f3af; Unity UI 性能优化终极指南 — Sprite篇 &#x1f9e9; Sprite 是什么&#xff1f;—— 渲染的基石与性能的源头 在Unity的2D渲染管线中&#xff0c;Sprite 扮演着至关重要的角色。它不仅仅是2D图像资源本身&#xff0c;更是GPU进行渲染批处理&#xff08;Batch…

【git】把本地更改提交远程新分支feature_g

创建并切换新分支 git checkout -b feature_g 添加并提交更改 git add . git commit -m “实现图片上传功能” 推送到远程 git push -u origin feature_g

vue中加载Cesium地图(天地图、高德地图)

目录 1、将下载的Cesium包移动至public下 2、首先需要将Cesium.js和widgets.css文件引入到 3、 新建Cesium.js文件&#xff0c;方便在全局使用 4、新建cesium.vue文件&#xff0c;展示三维地图 1、将下载的Cesium包移动至public下 npm install cesium后​​​​​​​ 2、…

Elasticsearch的插件(Plugin)系统介绍

Elasticsearch的插件(Plugin)系统是一种扩展机制,允许用户通过添加自定义功能来增强默认功能,而无需修改核心代码。插件可以提供从分析器、存储后端到安全认证、机器学习等各种功能,使Elasticsearch能够灵活适应不同的应用场景和业务需求。 一、插件的核心特点 模块化扩展…

基于 openEuler 22.03 LTS SP1 构建 DPDK 22.11.8 开发环境指南

基于 openEuler 22.03 LTS SP1 构建 DPDK 22.11.8 开发环境指南 本文详细介绍了在 openEuler 22.03 LTS SP1 操作系统上构建 DPDK 22.11.8 开发环境的完整流程。DPDK 20 版本之后采用 mesonninja 的编译方式&#xff0c;与早期版本有所不同。本文内容也可作为其他 Linux 发行版…

微服务网关SpringCloudGateway+SaToken鉴权

目录 概念 前置知识回顾 拿到UserInfo 用于自定义权限和角色的获取逻辑 最后进行要进行 satoken 过滤器全局配置 概念 做权限认证的时候 我们首先要明确两点 我们需要的角色有几种 我们需要的权限有几种 角色 分两种 ADMIN 管理员 &#xff1a;可管理商品 CUSTIOMER 普通…

Spring Cloud Gateway 中自定义验证码接口返回 404 的排查与解决

Spring Cloud Gateway 中自定义验证码接口返回 404 的排查与解决 问题背景 在一个基于 Spring Cloud Gateway WebFlux 构建的微服务项目中&#xff0c;新增了一个本地验证码接口 /code&#xff0c;使用函数式路由&#xff08;RouterFunction&#xff09;和 Hutool 的 Circle…

Dify中聊天助手、agent、文本生成、chatflow、工作流模式解读分析与对比

一次解读 1. 聊天助手 (Chat Assistant) 情景定位 (Situation): 你需要创建一个可以与用户进行多轮对话的AI应用&#xff0c;例如客服机器人、信息查询助手、或一个特定领域的虚拟专家。目标明确 (Purpose): 核心目标是理解并响应用户的连续提问&#xff0c;维持对话的上下文…

使用Node.js分片上传大文件到阿里云OSS

阿里云OSS的分片上传&#xff08;Multipart Upload&#xff09;是一种针对大文件优化的上传方式&#xff0c;其核心流程和关键特性如下&#xff1a; 1. ‌核心流程‌ 分片上传分为三个步骤&#xff1a; 初始化任务‌&#xff1a;调用InitiateMultipartUpload接口创建上传任务…

C++ if语句完全指南:从基础到工程实践

一、选择结构在程序设计中的核心地位 程序流程控制如同城市交通网络&#xff0c;if语句则是这个网络中的决策枢纽。根据ISO C标准&#xff0c;选择结构占典型项目代码量的32%-47%&#xff0c;其正确使用直接影响程序的&#xff1a; 逻辑正确性 执行效率 可维护性 安全边界 …

【大模型LLM学习】Flash-Attention的学习记录

【大模型LLM学习】Flash-Attention的学习记录 0. 前言1. flash-attention原理简述2. 从softmax到online softmax2.1 safe-softmax2.2 3-pass safe softmax2.3 Online softmax2.4 Flash-attention2.5 Flash-attention tiling 0. 前言 Flash Attention可以节约模型训练和推理时间…

python打卡day46@浙大疏锦行

知识点回顾&#xff1a; 不同CNN层的特征图&#xff1a;不同通道的特征图什么是注意力&#xff1a;注意力家族&#xff0c;类似于动物园&#xff0c;都是不同的模块&#xff0c;好不好试了才知道。通道注意力&#xff1a;模型的定义和插入的位置通道注意力后的特征图和热力图 内…