题目链接
https://leetcode-cn.com/problems/3sum/
解法思路
先对数组进行排序,排序完之后对数组进行遍历,每遍历一个元素设置左右两个指针,左指针指向当前元素的下一个元素,右指针指向数组最后一个元素,然后对当前元素,左指针指向元素,右指针指向元素进行相加,如果相加的和大于0,则将右指针左移(减少总和),如果小于0,则将左指针右移(增大总和),如果等于0,则当前元素、左指针元素、右指针元素满足题目要求。
但是一个元素可能有多种组合满足题目要求,如:[-2, 0, 1, 1, 1, 1, 2],遍历到2时,满足=0的结果集有[-2, 1, 1]和[-2, 0, 2]有两个解,但是按我们以上的逻辑只是移动左右指针求和,[-2, 1, 1]这个答案会出现两次,这样子答案就会出现重复值,所以我们要做一层过滤,如果左指针元素和左指针右边元素值相等(即nums[left] == nums[left + n]),则将左指针持续右移,同理,右指针元素如果和右指针左边元素相等(即nums[right] == nums[right - 1]),则将右指针持续左移。
解法代码
func threeSum(nums []int) [][]int {
length := len(nums)
var result [][]int
if length < 3 {
return result
}
// 排序
quickSort(nums, 0, length-1)
var left, right int
for i := 0; i < length-1; i++ {
// 相同组合的跳过
if i > 0 && nums[i] == nums[i-1] {
continue
}
// 左右指针所在位置
left, right = i+1, length-1
for left < right {
sum := nums[i] + nums[left] + nums[right]
if sum > 0 {
right--
} else if sum < 0 {
left++
} else {
item := []int{nums[i], nums[left], nums[right]}
result = append(result, item)
for left < right && nums[left] == nums[left + 1] {
left++
}
if left < right && nums[right] == nums[right - 1] {
right--
}
left++
right--
}
}
}
return result
}
func quickSort(sortArray []int, left, right int) {
if left < right {
pos := partition(sortArray, left, right)
quickSort(sortArray, left, pos-1)
quickSort(sortArray, pos+1, right)
}
}
func partition(sortArray []int, left, right int) int {
key := sortArray[right]
i := left - 1
for j := left; j < right; j++ {
if sortArray[j] <= key {
i++
sortArray[i], sortArray[j] = sortArray[j], sortArray[i]
}
}
sortArray[i+1], sortArray[right] = sortArray[right], sortArray[i+1]
return i + 1
}