描述:
给定一个包含n个整数的数组nums,判断nums中是否存在三个元素a,b,c,使得a+b+c=0 ?找出所有满足条件且不重复的三元组
注意:答案中不可以包含重复的三元组
例:给定数组 nums=[-1, 0, 1, 2, -1, -4]
满足要求的三元集合为:[[-1, 0, 1], [-1, -1, 2]]
一、暴力法
思路:数组先从小到大的顺序排序,然后遍历数组,取3个数判断它们的和是否等于0,存储组合是,判断该组合是否存储过,目的是去重
时间复杂度:O(n^3)
具体实现:
func threeSum(_ nums: [Int]) -> [[Int]] {
if nums.count == 0 {
return []
}
let nums = nums.sorted { (a, b) -> Bool in
return a < b
}
var array : [[Int]]! = [[Int]]()
for i in 0..<nums.count-2 {
let a = nums[i]
var j = i+1
while j < nums.count-1{
let b = nums[j]
var k = j+1
while k < nums.count{
let c = nums[k]
if a+b+c == 0{
let arr = [a,b,c]
//去重:看结果数组中是否已经包含该组合,若包含则继续往下,若不包含,则加入结果数组
if !array.contains(arr){
array.append(arr)
}
}
k = k+1
}
j = j+1
}
}
return array
}
二、双指针法
思路:固定一个值,找另外二个值它们和等于 0,这两个数的寻找利用双指针,左指针指向1,右指针指向最后一个数,依次向中间遍历
时间复杂度:O(nlog(n))
具体实现:
/*
固定一个值,找另外二个值它们和等于 0,
如何找另外两个值,用的是双指针!
*/
func threeSum(_ nums: [Int]) -> [[Int]] {
if nums.count == 0 {
return []
}
let nums = nums.sorted { (a, b) -> Bool in
return a < b
}
let len = nums.count
var array : [[Int]] = [[Int]]()
for i in 0..<len {
if i>0 && nums[i] == nums[i-1] {
continue
}
var left = i+1
var right = len-1
while left < right {
let tmp = nums[i]+nums[left]+nums[right]
//判断三个数的和是否等于0
if tmp==0 {
array.append([nums[i], nums[left], nums[right]])
//当左指针的数等于其后一个数时,左指针往右移一位
//其目的是:去除重复的数
while left<right && nums[left]==nums[left+1]{
left = left+1
}
//当右指针的数等于其前一个数时,右指针往左移一位
while left<right && nums[right]==nums[right-1]{
right = right-1
}
left = left+1
right = right-1
}else if tmp>0 {
//三数之和>0时,将右指针往左移一位
right = right - 1
}else{
//三数之和<0时,将左指针往右移一位
left = left+1
}
}
}
return array
}