15. 三数之和 中等
给你一个包含 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
代码参考:
package main
import (
"fmt"
"sort"
)
func main() {
fmt.Println(threeSum([]int{-1, 0, 1, 2, -1, -4})) // [[-1 -1 2] [-1 0 1]]
fmt.Println(badTwoSum([]int{-1, 0, 1, 2, -1, -4})) // [[-1 -1 2] [-1 0 1]]
fmt.Println(threeSum([]int{-2, 0, 0, 2, 2})) // [[-2 0 2]]
}
// 处理结果与元素原顺序无关,可排序预处理,方便去重
// 使用双指针遍历后部分剩余数组
func threeSum(nums []int) [][]int {
sort.Ints(nums) // [-4 -1 -1 0 1 2] // 预排序有 2 个好处:去重 & 指导双指针的下一步方向
n := len(nums)
var res [][]int
for i, num := range nums {
if num > 0 {
break // 优化,再往后三个正数和不可能为 0
}
// 第一层遍历数向前去重
if i > 0 && nums[i] == nums[i-1] { // 因为双指针从 i 之后取,不能使用 nums[i] == nums[i+1] 向后去重
continue
}
l, r := i+1, n-1
for l < r {
sum := num + nums[l] + nums[r]
switch {
case sum > 0:
r--
case sum < 0:
l++
default:
res = append(res, []int{num, nums[l], nums[r]})
// 第二层候选数向后去重
for l < r && nums[l] == nums[l+1] {
l++
}
for r > l && nums[r] == nums[r-1] {
r--
}
l++
r--
}
}
}
return res
}
// twoSum 的思路,不好
func badTwoSum(nums []int) [][]int {
// 避开全是 0 的 case // ugly
if len(nums) >= 3 {
allZero := true
for _, num := range nums {
if num != 0 {
allZero = false
}
}
if allZero {
return [][]int{{0, 0, 0}}
}
}
n := len(nums)
num2index := make(map[int]int, n)
for i, num := range nums {
num2index[num] = i
}
// 获取三元组
var res [][]int
for i := 0; i < n; i++ {
for j := i + 1; j < n; j++ {
remain := 0 - (nums[i] + nums[j])
if k, ok := num2index[remain]; ok && j != k && i != k {
res = append(res, []int{nums[i], nums[j], remain})
}
}
}
// 剔除重复的三元组
m := make(map[string][]int)
for i := range res {
sort.Ints(res[i])
m[intStr(res[i])] = res[i]
}
var arrs [][]int
for _, arr := range m {
arrs = append(arrs, arr)
}
return arrs
}
// trick // 使得整数数组能做 map 的 key
func intStr(nums []int) string {
str := ""
for _, num := range nums {
str += fmt.Sprintf("%d_", num)
}
return str
}
最后编辑: kuteng 文档更新时间: 2021-06-05 10:16 作者:kuteng