方法:双指针
这段代码的目标是找到数组中所有满足三数之和为 0 的不重复元素组合,并将其存储在 ans
数组中返回。代码中使用双指针法来遍历数组,通过设定首尾两个指针,逐渐逼近目标值。具体流程如下:
- 将数组排序,使得相同的元素相邻。
- 外层循环遍历数组中的每个元素,用指针
first
指向当前元素。 - 如果当前元素与前一个元素相同,则跳过,以去重。
- 内层循环中,使用指针
second
和third
分别指向first
后面的第一个元素和数组的最后一个元素。 - 如果
second
指向的元素与前一个元素相同,则跳过,以去重。 - 判断
nums[second] + nums[third]
是否大于目标值 `
- 时间复杂度:代码中使用了两层循环,外层循环的时间复杂度为 O(n),内层循环根据具体情况可能是 O(n) 或 O(nlogn)。整体来说,时间复杂度为 O(n^2) 或 O(n^2logn)。
- 空间复杂度:创建了一个二维数组
ans
来存储结果,其空间复杂度与最终结果的数量成正比,所以为 O(n)。
func main(){
nums3:=[]int{0,0,0,0,0,0,0,1,1,-1,-1,2,0,-2}
ansMatrix:=threeSum(nums3)
fmt.Println(ansMatrix)
}
func threeSum(nums []int) [][]int {
n:=len(nums)
sort.Ints(nums)//给数组排序
ans:=make([][]int,0)//创建一个存放三数之和元素的数组的数组
//
for first:=0;first<n;first++{
if first>0&&nums[first]==nums[first-1]{//用nums[first]==nums[first-1]来判断排好序的数组中当前元素是否和上一个元素相等,
// 如果和上一个元素相等,说明上一层已经遍历过这个元素了,所以就要给不同的三元数组之间去重。
//continue的意思是如果if满足条件,执行continue,不用继续执行后面的语句,直接进行迭代first++。
continue
}
third:=n-1//定义第三个元素的指针
target:=-1*nums[first]//定义-a的变量,用-a来判断b+c是否等于-a
//第二个元素b从first的下一个开始
for second:=first+1;second<n;second++{//定义第二个元素b的指针,第二个元素不能与第三个元素相加,所以second<third
//b也是要去重,因为是排好序的数组,相临的两个元素相同的话要去重
if second>first+1 && nums[second]==nums[second-1] {
continue
}
//b+c>target的话,最大的元素third要减小一点
for second<third&&nums[second]+nums[third]>target{
third--
}
//如果second层遍历到和third相同的位置了,说明没有找到b+c,而第二个元素不能与第三个元素相加,所以直接结束循环
//(因为second不动的时候,third会动,所以有可能相等)
if second==third{
break
}
//每轮second迭代,都把数组存下来
if nums[second]+nums[third]==target{
ans=append(ans,[]int{nums[first],nums[second],nums[third]})
}
}
}
return ans
}