持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第8天,点击查看活动详情
一 描述
给你一个包含 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
- -10^5 <= nums[i] <= 10^5
二 分析
看了高票的几个题解,核心思想大家基本是一致的,有些专业的说法说排序+双指针+剪枝,看他们写的细节里面包括代码都有问题,有些用几个嵌套while,虽然有点眼前一亮,但是可读性并不是很好,是很多人包括我自己吐槽的点,仔细想了下其实代码也挺简单的,只是大家术语听起来有点高大上吧,不多说了,这里思想也是如此。
暴力法
三重遍历解决,保量结果使用map去重判断
func threeSum(num []int) [][]int {
sort.Ints(num)
isMapExist:=make(map[string]int);
res :=[][]int{}
for i:=0;i<len(num);i++ {
if(num[i] > 0) {
continue
}
for j:=i+1;j<len(num);j++ {
for z:=j+1;z<len(num);z++ {
if i!=j && j!=z && i!=z {
if num[i] + num[j] + num[z] == 0 {
arr :=[]int{num[i],num[j],num[z]};
str := strconv.Itoa(num[i]) + "_" +strconv.Itoa(num[j]) + "_" + strconv.Itoa(num[z]) + "_";
if _,ok := isMapExist[str];ok {
continue;
}
res = append(res,arr)
isMapExist[str] = 0;
}
}
}
}
}
return res
}
三 总结
暴力解法肯定是不行的,优化方案如下
- 排序数组(由小到大)
- 遍历数组,发现当前数值>0,则可以跳过。
- 在当前数组的位置,对后面的数字进行遍历,使用前后俩个角标,一大一小来进行匹配,找到num[i]+num[j]+num[z] = 0,则移动角标,找下一对。
- 因为是顺序遍历的,若是某个数字和之前重复,则说明结果集合已经被算过了。
- 为了防止找出的三个数集合有重复,这里也可以使用一个map判断去重实现。