题目如下:(leetcode 热题100)
给你一个整数数组 nums ,判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i != j、i != k 且 j != k ,同时还满足 nums[i] + nums[j] + nums[k] == 0 。请
你返回所有和为 0 且不重复的三元组。
注意: 答案中不可以包含重复的三元组。
对于这个题目,解决方法有很多种,但是相对简单的就是双指针,我们可以把这个题目看作是两数之和的升级版。
1.我们便利数组,这个是三数中的第一个A
2.我们用0 - A等于 B + C。
按照这个思路,我们来解决这个问题 首先我们考虑一下边界问题:
if nums.count < 3 {return [[]]}
如果数组的长度大于等于3,我们就正常的遍历计算即可
在遍历之前,我们需要把数组进行一个排序,这个可以直接使用swift自带的排序。他的效率非常高,也为我们后续的筛选节省了很多时间
let newSums = nums.sorted()
var totalSum: [[Int]] = []
现在我们可以开始遍历了。这样的好处是我们在计算的时候指针的移动更加方便了。
我们使用两个指针,left和right,一个指在前面,一个指在末尾。 因为newSums是已经排序了的。那么我们就知道我们的指针该怎么移动了
比如left对应的值 + right对应的值大于我们需要的值,那说明我们需要把right指针往左移动,如果left对应的值 + right对应的值小于我们需要的值,说明我们需要left右移动,保证我们的结果跟他靠近直到等于。
这里我们写出我们的部分代码
for i in newNums {
if i > 0 && newNums[i] == newNums[i-1] {//如果这个值相同的话需要过滤掉,不然结果重复了
continue
}
var left = i + 1 (因为之前的元素遍历过,所以要从当前元素的下一位开始遍历)
var right = nums.count - 1
while left < right {
let sum = newSums[i] + newSums[left] + newSums[right]
if sum > 0 {
right -= 1
} else if sum < 0 {
left += 1
} else {
//这个地方需要考虑到去重,因为newNums的元素可能有好多过重复的,但是我们只需要第一个计算的值,其他的我们跳过,下面我们会讲解
}
}
}
当然这么做还有个问题,我们如果数组的元素相同的话,我们需要考虑到过滤掉相同的数据带来的重复问题
// 如果sum == 0 left += 1, right -= 1,左指针右移,右指针左移
// 我们还需要考虑到左移右移之后 元素重复的问题,如果重复需要跳过,不然结果会重复
totalSum.append(newSums[i] + newSums[left] + newSums[right])
left += 1
right -= 1
while left < right && newSums[left] == newSums[left - 1] {
left += 1
}
while left < right && newSums[right] == newSums[right + 1] {
right -= 1
}
上面差不多就是我们的整体代码
func threeSum(_ nums: [Int]) -> [[Int]] {
if nums.count < 3 {return [[]]}
let newSums = nums.sorted()
var totalSums: [[Int]] = []
for i in 0..<newSums.count {
if i > 0 && newSums[i] == newSums[i-1] {
continue
}
var left = i + 1
var right = newSums.count - 1
while left < right {
let sum = newSums[i] + newSums[left] + newSums[right]
if sum > 0 {
right -= 1
} else if sum < 0 {
left += 1
} else {
totalSums.append([newSums[i], newSums[left], newSums[right]])
left += 1
right -= 1
while** (left < right) && newSums[left] == newSums[left - 1] {
left += 1
}
while (left < right) && newSums[right] == newSums[right + 1] {
right -= 1
}
}
}
}
return totalSums
}