【LeetCode】15. 三数之和

147 阅读2分钟

三数之和

给你一个包含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 = []
输出:[]

思路

  • 本题主要是对三元组进行去重,如果是map,key不可为切片,因此map方法不能使用。
  • 针对本题,首先将数组排序,然后在遍历数组的过程中去除重复解。
  • 在遍历数组的时候:用i确定开始遍历的位置(也是target的位置),如果当前元素和前面的元素相等,则跳出本次循环,去除重复解。
  • 继续使用左右指针在区间[i+1,len(nums)-1]寻找使得nums[left]+nums[right]+target==0的解。
    • 如果nums[left]+nums[right]+target==0,如果在寻找的过程中left和right与下一位置重复,则去除重复解,并同时将left,right移到下一位置,寻找新的解
    • 如果nums[left]+nums[right]+target<0,则left右移
    • 如果nums[left]+nums[right]+target>0,则right左移

解法

func threeSum(nums []int) [][]int {
    sort.Ints(nums)
    res:=[][]int{}
    for i:=0;i<len(nums);i++{ // 在遍历数组的时候:用i确定开始遍历的位置(也是target的位置)
        left:=i+1
        right:=len(nums)-1
        if i>0&&nums[i]==nums[i-1] // 如果当前元素和前面的元素相等,则跳出本次循环,去除重复解
            continue
        }
        if nums[i]>0{ // 排序后i对应的位置为最小,其后面的均大于它
            break
        }
        target:=nums[i] // 将target初始化为索引为i的元素
        for left<right{ // 对区间[left,right]进行左右指针查找
            if nums[left]+nums[right]+target>0{ // 如果nums[left]+nums[right]+target>0,则right左移
                right--
            }else if nums[left]+nums[right]+target<0{ // 如果nums[left]+nums[right]+target<0,则left右移
                left++
            }else{ // 如果nums[left]+nums[right]+target==0
                res=append(res,[]int{target,nums[left],nums[right]})
                left++
                right--
                for left<right&&nums[left]==nums[left-1]{ // 如果left与下一位置重复,则将left移到下一位
                    left++
                }
                for left<right&&nums[right]==nums[right+1]{ // 如果right与下一位置重复,则将right移到下一位
                    right--
                }
            }
        }
    }
    return res
}