三数之和——排序+双指针

77 阅读1分钟

image.png

方法1:

  1. 因为不能包含重复三元组,所以先排序,这样更容易去重
  2. 排序过后遍历第一个数,并保证从第二遍开始与上一次的值不相同,从而起到去重的目的
  3. 在遍历第一个数的时候,因为已经确定了一个值,所以问题就从刚开始的三元组问题变成了两元组问题,我们只需要将另外两个元素的和等于负的第一个元素的值(我们把它记为a)就可以满足三数之和为0,此时就可以用双指针来解决问题
  4. 此时让右指针指向最后一个位置
  5. 所以在遍历第一个数的时候遍历第二个数(也就是让左指针指向第一个数的下一个位置),并且与第2步一样从第二遍开始要保证与上一次的值不同,并且保证左<右()
  6. 遍历第二个数的时候(也就是左指针右移的过程中),如果两数之和大于a,则让右指针左移直到两数之和重新满足小于a,并且在移动的过程中保证右指针 > 左指针,
  7. 因为在第6步移动右指针的过程结束后无法确定是因为左右重合跳出循环的,还是因为值小于a跳出循环的,所以要再次判断是否 左==右 ,如果是则break
  8. 在第二层循环中有满足左值加右值==a,则存入答案中
func threeSum(nums []int) [][]int {
    sort.Ints(nums)
    ans := [][]int{}
    n := len(nums)
    for i := 0; i < n; i++ {
        if i > 0 && nums[i] == nums[i-1] {
            continue
        }
        r := n-1
        a := -nums[i]
        for l := i+1; l < r; l++ {
            if l > i+1 && nums[l] == nums[l-1] {
                continue
            }
            for r > l && nums[l] + nums[r] > a{
                r--
            }
            if r == l {
                break
            }
            if nums[l] + nums[r] == a { 
                ans = append(ans,[]int{nums[i],nums[l],nums[r]})
            }
        }
    }
    return ans
}