1.题目
给你一个包含 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
2.解题思路
- 方法一:排序 + 双指针
标签:数组遍历
首先对数组进行排序,排序后固定一个数nums[i,再使用左右指针指向numsi后面的两端,数字分
别为nms[L]和nums[R],计算三个数的和sum判断是否满足为O,满足则添加进结果集
如果nums[i大于0,则三数之和必然无法等于0,结束循环
如果nums[i=nums[i-1],则说明该数字重复,会导致结果重复,所以应该跳过
当sum=0时,nums[L]==numsL+1]则会导致结果重复,应该跳过,L++
当sum=0时,numsR=nums[R-1]则会导致结果重复,应该跳过,R–
时间复杂度:O(n2),n为数组长度
3.代码
object Solution {
import java.util
import scala.collection.mutable.{ArrayBuffer, ListBuffer}
import scala.util.control.Breaks
def threeSum(nums: Array[Int]): List[List[Int]] = {
val listBuffer = new ListBuffer[List[Int]]()
val len = nums.length
if(nums == null || len<3) return listBuffer.toList
util.Arrays.sort(nums) // 排序
val loop = new Breaks
val loop2 = new Breaks
loop.breakable{
for (i<-0 to len-1){
loop2.breakable {
if (nums(i) > 0) loop.break()
if (i > 0 && nums(i) == nums(i - 1)) loop2.break() // 去重操作
var L = i + 1
var R = len - 1
while (L < R) {
val sum = nums(i) + nums(L) + nums(R)
if (sum == 0) {
listBuffer.append(List(nums(i), nums(L), nums(R)))
while (L < R && nums(L) == nums(L + 1)) L = L + 1 // 去重操作
while (L < R && nums(R) == nums(R - 1)) R = R - 1 // 去重操作
L = L + 1
R = R - 1
}
else if (sum < 0) L = L + 1
else if (sum > 0) R = R - 1
}
}
}
}
return listBuffer.toList
}
}
4.复杂度分析
- 时间复杂度:O(N2),其中N是数组nums的长度。
- 空间复杂度:O(logN)。我们忽略存储答案的空间,额外的排序的空间复杂度为O(logN)。然而我们修改了输入的数组nums,在实际情况下不一定允许,因此也可以看成使用了一个额外的数组存储了nums的副本并进行排序,空间复杂度为O(N)。