养成一个小习惯,每天复习一题~
题目
Given an integer array nums, return all the triplets [nums[i], nums[j], nums[k]] such that i != j, i != k, and j != k, and nums[i] + nums[j] + nums[k] == 0.
Notice that the solution set must not contain duplicate triplets.
Example 1:
Input: nums = [-1,0,1,2,-1,-4]
Output: [[-1,-1,2],[-1,0,1]]
Explanation:
nums[0] + nums[1] + nums[2] = (-1) + 0 + 1 = 0.
nums[1] + nums[2] + nums[4] = 0 + 1 + (-1) = 0.
nums[0] + nums[3] + nums[4] = (-1) + 2 + (-1) = 0.
The distinct triplets are [-1,0,1]
and [-1,-1,2]
.
Notice that the order of the output and the order of the triplets does not matter.
Example 2:
Input: nums = [0,1,1]
Output: []
Explanation: The only possible triplet does not sum up to 0.
Example 3:
Input: nums = [0,0,0]
Output: [[0,0,0]]
Explanation: The only possible triplet sums up to 0.
Constraints:
3 <= nums.length <= 3000
-105 <= nums[i] <= 105
解
简单解法:
复杂度Θ(n^2)
func threeSum(nums []int) [][]int {
result := make([][]int, 0)
sort.Slice(nums, func(i,j int) bool {
return nums[i] < nums[j]
}) // 排序
for i := 0; i < len(nums) - 1;i++ {
// 第一个元素去重
if i > 0 && nums[i] == nums[i-1] {
continue
}
l, r := i+1, len(nums)-1
for l < r {
sum := nums[i] + nums[l] + nums[r]
if sum < 0 {
l += 1
} else if sum > 0 {
r -= 1
} else {
result = append(result, []int{nums[i], nums[l], nums[r]})
// 第二个元素去重
for l < r && nums[l] == nums[l+1] {
l += 1
}
// 第三个元素去重
for l < r && nums[r] == nums[r-1] {
r -= 1
}
l++
r--
}
}
}
return result
}
另一种思路:
回溯法,求符合条件的子集。缺点:运行耗时长,会Time Limit Exceede
。
func isDuplicate(l1 []int, l2 []int) bool {
sort.Slice(l1, func(i, j int) bool {
if l1[i] > l1[j] {
return true
}
return false
})
sort.Slice(l2, func(i, j int) bool {
if l2[i] > l2[j] {
return true
}
return false
})
duplicate := true
for i, _ := range l2 {
if l1[i] != l2[i] {
duplicate = false
}
}
return duplicate
}
func backtrack(result *[][]int, nums []int, path []int, sum int, startIndex int) {
if len(path) == 3 && sum == 0 {
is := false
tmp := make([]int, 3)
copy(tmp, path)
for _, v := range *result {
if isDuplicate(v, tmp) {
is = true
break
}
}
if !is {
res := make([]int, 3)
copy(res, path)
*result = append(*result, tmp)
}
}
if len(path) == 3 {
return
}
for i := startIndex; i < len(nums); i++ {
path = append(path, nums[i])
backtrack(result, nums, path, sum+nums[i], i+1)
path = path[:len(path)-1]
}
}
func threeSum(nums []int) [][]int {
result := make([][]int, 0)
path := make([]int, 0)
backtrack(&result, nums, path, 0, 0)
return result
}