题目链接

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]),则将右指针持续左移。

解法代码

  1. func threeSum(nums []int) [][]int {
  2. length := len(nums)
  3. var result [][]int
  4. if length < 3 {
  5. return result
  6. }
  7. // 排序
  8. quickSort(nums, 0, length-1)
  9. var left, right int
  10. for i := 0; i < length-1; i++ {
  11. // 相同组合的跳过
  12. if i > 0 && nums[i] == nums[i-1] {
  13. continue
  14. }
  15. // 左右指针所在位置
  16. left, right = i+1, length-1
  17. for left < right {
  18. sum := nums[i] + nums[left] + nums[right]
  19. if sum > 0 {
  20. right--
  21. } else if sum < 0 {
  22. left++
  23. } else {
  24. item := []int{nums[i], nums[left], nums[right]}
  25. result = append(result, item)
  26. for left < right && nums[left] == nums[left + 1] {
  27. left++
  28. }
  29. if left < right && nums[right] == nums[right - 1] {
  30. right--
  31. }
  32. left++
  33. right--
  34. }
  35. }
  36. }
  37. return result
  38. }
  39. func quickSort(sortArray []int, left, right int) {
  40. if left < right {
  41. pos := partition(sortArray, left, right)
  42. quickSort(sortArray, left, pos-1)
  43. quickSort(sortArray, pos+1, right)
  44. }
  45. }
  46. func partition(sortArray []int, left, right int) int {
  47. key := sortArray[right]
  48. i := left - 1
  49. for j := left; j < right; j++ {
  50. if sortArray[j] <= key {
  51. i++
  52. sortArray[i], sortArray[j] = sortArray[j], sortArray[i]
  53. }
  54. }
  55. sortArray[i+1], sortArray[right] = sortArray[right], sortArray[i+1]
  56. return i + 1
  57. }