题目描述:
给你一个包含 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 = []输出:[]示例 3:输入:nums = [0]输出:[]提示:0 <= nums.length <= 3000-105 <= nums[i] <= 105
思路:
根据题意,获取三个数之和为0,实质上就是对给出的数组进行全排列,然后选出结果等于0的,再去掉重复的。题目中给出的nums的长度范围是0-3000,由此可以猜测,这道题的时间复杂度最多就O(n^2),如果用三重循环去暴力解答 ,那肯定会超时。
去重
对于去重的操作,可以使用哈希表,这样做需要找出所有结果为0的集合,并且使用哈希表存储,时间复杂度和空间复杂度都比较高。因此可以考虑对原数组进行排序,然后固定三个数中的其中一个,另外两个数使用双指针来进行去重的操作,如果两个相邻的数相同,那就可以将指针前移或者后移。
固定第一个数比较简单,同样的套路可应用于最接近的三数之和以及四数之和。
/** @lc app=leetcode.cn id=15 lang=golang** [15] 三数之和*/// @lc code=startfunc threeSum(nums []int) [][]int {quickSort(nums)var buf [][]intfor i := 0; i < len(nums); i++ {if i > 0 && nums[i] == nums[i-1] {continue}start, end := i+1, len(nums)-1//固定第一个数for start < end {if start > i+1 && start < len(nums) && nums[start] == nums[start-1] {start++continue}if end < len(nums)-1 && end >= start && nums[end] == nums[end+1] {end--continue}if nums[i]+nums[start]+nums[end] > 0 {end--} else if nums[i]+nums[start]+nums[end] < 0 {start++} else {buf = append(buf, []int{nums[i], nums[start], nums[end]})start++end--}}}return buf}func quickSort(nums []int) {if len(nums) < 2 {return}head, tail := 0, len(nums)-1reference := nums[0]i := 1for head < tail {if nums[i] < reference {nums[head], nums[i] = nums[i], nums[head]head++i++ //这里的i已经进行过自增了,在else里面就不需要了,快速排序不用遍历完整个数组} else {nums[tail], nums[i] = nums[i], nums[tail]tail--}}quickSort(nums[:head])quickSort(nums[head+1:])}// @lc code=end
排序是自己写的快排,其实可以使用官方的sort包来进行处理,这样写只是为了复习。。。
LeetCode
