三数之和
描述
给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?请你找出所有和为 0 且不重复的三元组。
注意: 答案中不可以包含重复的三元组。
示例1
输入:nums = [-1,0,1,2,-1,-4]
输出:[[-1,-1,2],[-1,0,1]]
示例2
输入:nums = []
输出:[]
示例3
输入:nums = [0]
输出:[]
约束条件
0 <= nums.length <= 3000
-105 <= nums[i] <= 105
思路:排序+双指针
-
首先排序数组
nums,使得取得的三数 (a, b, c) 满足 a≤b≤c ,这样后续计算就不会出现 (b, a, c)、(c, b, a) 的组合,达到去重的效果。 -
在
0..<(len - 2)范围内枚举第一个数a,并在之后的区间找出所有满足 a+b+c=0 的b、c。-
如果 a > 0,那么
b、c也大于0,则三数之和必不为 0,则结束循环。 -
如果
a和 前一个数重复,此数已经选取过,则跳过本次循环。 -
定义左右指针
left、right于 a 后续区间的两端(left 为 b,right 为c),根据 sum = a + left + right 的结果移动指针,找出满足三数之和为 0 的结果(指针移动要注意去重,即循环移动指针直到 新值 != 旧值)- 如果 sum = 0,则记录结果,同时收缩左右指针
- 如果 sum > 0 ,左移右指针
- 如果 sum < 0 ,右移左指针
-
复杂度分析
- 时间复杂度:O(n2) ,数组排序复杂度为 O(nlogn) ,枚举
a的时间复杂度为 O(n) ,双指针滑动查找b、c的时间复杂度为O(n) ,所以总的时间复杂度为 O(nlogn)+O(n2) = O(n2) - 空间复杂度:O(n)|O(logn) ,空间复杂度取决于排序使用的空间复杂度。
题解(swift)
class Solution {
func threeSum(_ nums: [Int]) -> [[Int]] {
var res = [[Int]]()
let len = nums.count
// 排序数组
let nums = nums.sorted()
// 不满足三数
if len < 3 {
return res
}
// 枚举数 a,使用双指针遍历 a 之后的区间,找到满足 a+b+c=0 的所有不重复值
for fir in 0..<(len - 2) {
// 第一个元素大于0不存在三数和为0,直接结束
if nums[fir] > 0 {
break
}
// 第一个元素去重
if fir > 0 && nums[fir] == nums[fir - 1] {
continue
}
// 定义左右指针在 a 后区间的两端,根据情况收缩指针
var left = fir + 1,right = len - 1
while right > left {
let sum = nums[fir] + nums[left] + nums[right]
if sum == 0 {
//三数和为0,添加到数组,同时收缩两端指针
res.append([nums[fir], nums[left], nums[right]])
repeat {
left += 1
} while left < right && nums[left] == nums[left - 1]
repeat {
right -= 1
} while left < right && nums[right] == nums[right + 1]
} else if sum > 0 {
// sum 太大,左移右指针
right -= 1
} else {
// sum 太大,右移左指针
left += 1
}
}
}
return res
}
}