给你一个整数数组 nums ,判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i != j、i != k 且 j != k ,同时还满足 nums[i] + nums[j] + nums[k] == 0 。请你返回所有和为 0 且不重复的三元组。

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

示例 1:

输入:nums = [-1,0,1,2,-1,-4]

输出:[[-1,-1,2],[-1,0,1]]

解释:

nums[0] + nums[1] + nums[2] = (-1) + 0 + 1 = 0 。

nums[1] + nums[2] + nums[4] = 0 + 1 + (-1) = 0 。

nums[0] + nums[3] + nums[4] = (-1) + 2 + (-1) = 0 。

不同的三元组是 [-1,0,1] 和 [-1,-1,2] 。

注意,输出的顺序和三元组的顺序并不重要。

示例 2:

输入:nums = [0,1,1]

输出:[]

解释:唯一可能的三元组和不为 0 。

示例 3:

输入:nums = [0,0,0]

输出:[[0,0,0]]

解释:唯一可能的三元组和为 0 。

提示:

3 <= nums.length <= 3000

-105 <= nums[i] <= 105

思路分析:

在解决“三数之和”问题时,分析和思路的推导过程如下:

  • 问题的要求和分析

    题目要求找到三个数的和为零,且需要输出所有不重复的三元组。数组中可能包含正数、负数和零,因此找到的三元组可能由正负数组合而成。

输入特点:数组中的数没有特定规律,可能是正数、负数、零。

输出要求:不重复的三元组,且它们的和为零。

最简单、直接的思路就是通过暴力求解,即:

对数组中的每一个元素,遍历所有的可能组合,找到符合条件的三元组。

暴力解法的时间复杂度为 O(n³),不满足题目要求。

  • 从暴力解法到优化

    在暴力解法中,确定了一个数后,剩下两个数的查找可以视为“两数之和”问题。如果我们能通过某种方式快速查找剩下的两个数,就能减少遍历的复杂度。

    常见的两数之和问题可以通过哈希表实现,但这里的关键点是,我们需要找的三元组不仅要和为零,还需要确保不重复,这增加了查找的难度。
  • 引入排序和双指针

    为了降低查找复杂度,我们可以先对数组进行排序。排序有两个好处:

    1.排序后的数组,便于使用双指针技巧快速查找剩余的两个数。

    2.排序可以帮助去除重复的解(因为相同的元素只需要考虑一次)。
  • 核心思想:

    固定一个数:遍历数组,固定其中一个数 nums[i]。

    寻找剩下两个数:通过双指针技巧,在剩余部分的数组中寻找和为 -nums[i] 的另外两个数。

  • 双指针的运用

    双指针技巧是指在有序数组中,使用两个指针(通常是头和尾)来进行查找的方式。

假设我们固定了 nums[i],需要在剩下的数组中找到两个数 nums[left] 和 nums[right],使得它们的和为 -nums[i]。

根据双指针的性质:

如果当前的三数之和 nums[i] + nums[left] + nums[right] 小于零,说明我们需要更大的数,于是左指针 left 右移。

如果当前的三数之和大于零,说明我们需要更小的数,于是右指针 right 左移。

如果找到三数之和为零,则保存结果,并同时移动两个指针,继续寻找其他可能的组合。

  • 去重问题

    由于可能存在重复的元素,结果中不能包含重复的三元组。因此,在实现中需要特别处理去重的情况:

遍历时,如果当前元素与前一个元素相同,则直接跳过,避免重复计算。

在找到一个符合条件的三元组后,需要跳过数组中与当前 left 和 right 指针相同的元素,确保不会重复处理相同的组合。

  • 为什么选择双指针?

    时间复杂度的优化:双指针法将暴力求解的复杂度从 O(n³) 降低到 O(n²),这是因为每次外层循环固定一个数时,剩下的部分只需要通过一次双指针查找就可以完成。

    排序的好处:排序虽然需要 O(n log n) 的时间,但在排序后的数组中,双指针法可以有效利用数组的有序性来快速调整查找范围,这使得整体复杂度得到了优化。

  • 总结思路

    最终解决这个问题的思路总结如下:

    排序:首先将数组排序,方便后续查找并去重。

    遍历数组:对于每一个 nums[i],将问题简化为在剩下的数组中寻找两个数使得三数之和为零。

    双指针查找:在有序数组中使用双指针查找,通过移动指针调整和的大小。

    去重处理:确保结果集中不包含重复的三元组,处理遍历中的重复元素。

点击查看代码
func threeSum(nums []int) [][]int {
sort.Ints(nums)
var res [][]int
for i := 0; i < len(nums)-2; i++ {
if i > 0 && nums[i] == nums[i-1] {
continue // 去重
}
left, right := i + 1, len(nums) - 1
for left < right {
sum := nums[i] + nums[left] + nums[right]
if sum == 0 {
res = append(res, []int{nums[i], nums[left], nums[right]})
// 跳过重复的 left 和 right
for left < right && nums[left] == nums[left+1] {
left++
}
for left < right && nums[right] == nums[right-1] {
right--
}
left++ // 更新 left
right-- // 更新 right
} else if sum < 0 {
left++
} else {
right--
}
}
}
return res
}

15. 三数之和 Golang实现的更多相关文章

  1. LeetCode 15. 三数之和(3Sum)

    15. 三数之和 15. 3Sum 题目描述 Given an array nums of n integers, are there elements a, b, c in nums such th ...

  2. Java实现 LeetCode 15 三数之和

    15. 三数之和 给定一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?找出所有满足条件且不重复的三元组. 注意:答案中不可以 ...

  3. 代码随想录第七天| 454.四数相加II、383. 赎金信 、15. 三数之和 、18. 四数之和

    第一题454.四数相加II 给你四个整数数组 nums1.nums2.nums3 和 nums4 ,数组长度都是 n ,请你计算有多少个元组 (i, j, k, l) 能满足: 0 <= i, ...

  4. 代码随想录算法训练营day07 | leetcode 454.四数相加II 383. 赎金信 15. 三数之和 18. 四数之和

    LeetCode 454.四数相加II 分析1.0 这个最直接暴力法,不过过于暴力了,害怕.jpg 失误 读题理解失误:题目要求的是四元组的个数,读完题到我这里成了输出四元组,悲哉 分析2.0 记录有 ...

  5. leetcode题目15.三数之和(中等)

    题目描述: 给定一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?找出所有满足条件且不重复的三元组. 注意:答案中不可以包含重 ...

  6. LeetCode——15. 三数之和

    给定一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?找出所有满足条件且不重复的三元组. 注意:答案中不可以包含重复的三元组. ...

  7. 【LeetCode】15.三数之和

    题目描述 1. 三数之和 给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?请你找出所有满足条件且不重复的三元组. 注意: ...

  8. LeetCode 15. 三数之和(3Sum)

    题目描述 给定一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?找出所有满足条件且不重复的三元组. 注意:答案中不可以包含重复 ...

  9. [Leetcode 15]三数之和 3 Sum

    [题目] Given an array nums of n integers, are there elements a, b, c in nums such that a + b + c = 0? ...

  10. 【每日一题】【位于index后的双指针&排序数组】15. 三数之和/NC54 数组中相加和为0的三元组-211117/220206

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

随机推荐

  1. 外部网关协议BGP

    不能全部使用RIP与OSPF的原因有二:互联网规模太大,自治系统间路由选择困难:自治系统间路由选择必须考虑有关策略. 在每一个自治系统中有两种不同功能的路由器,边界路由器和内部路由器. BGP四种报文 ...

  2. IstioCon 回顾 | 网易数帆的 Istio 推送性能优化经验

    在 IstioCon2022 上,网易数帆资深架构师方志恒从企业生产落地实践的视角分享了多年 Istio 实践经验,介绍了 Istio 数据模型,xDS 和 Istio 推送的关系,网易数帆遇到的性能 ...

  3. 诺基亚8110 4G手机强制格式化方法

    关机状态下,先按住上键,再按住开机键,出现开机动画时松开开机键,出现硬割界面下键选择第一个wipe用开机键确认yes,再次出现硬格界面,下键选择第二个wipe用开机键确认yes,再次出现硬格界面开机键 ...

  4. [oeasy]python0140_导入_import_from_as_namespace_

    导入import 回忆上次内容 上次学习了 try except   注意要点 半角冒号 缩进 输出错误信息   有错就报告 不要隐瞒 否则找不到出错位置 还可以用traceback把 系统报错信息原 ...

  5. 网络基础 CAS协议学习总结

    架构介绍 系统组件 CAS服务器和客户端构成了CAS系统体系结构的两个物理组件,它们通过各种协议进行通信. CAS服务器 CAS服务器是基于Spring Framework构建的Java servle ...

  6. Python 函数中箭头 (->)的用处

    Python 3 -> 是函数注释的一部分,表示函数返回值的类型. def useful_function(x) -> int: # Useful code, using x, here ...

  7. HCIA first

    每台电脑都有网线 网线连的是什么? 网线插在接入交换机 流量给入汇聚交换机 汇聚给核心交换机 核心交换机 堆叠是指将一台以上的交换机组合起来共同工作,以便在有限的空间内提供尽可能多的端口.多台交换机经 ...

  8. ambari+ bigtop 编译、打包、部署步骤总览

    1 ambari + bigtop 构建大数据基础平台 1.1 参考: 1.2 参考 amabri bigtop 打包部署 2 ambari+bigtop编译.打包.部署 2.0 基础环境准备 2.1 ...

  9. SQL连续查询问题拓展—记上海拼多多非技术岗面试真题

    真巧,昨天刚写了关于数据库连续问题的解决方案,没想到今天下午两点就有朋友在上海拼多多面试非技术岗位中就遇到了相似的问题.下面是原题: 一个最大连续支付失败的次数 有一张支付流水表pay;字段如下 id ...

  10. 微信支付APIV3私钥与证书配置

    1.加载商户私钥(privateKey:私钥字符串) 这个私钥是下载证书的的:apiclient_key.pem 2.转换下单时的证书 文档:https://github.com/wechatpay- ...