> 文章列表 > 15. 三数之和

15. 三数之和

15. 三数之和

题目

给你一个整数数组 nums ,判断是否存在三元组 [nums[i],nums[j],nums[k]][nums[i], nums[j], nums[k]][nums[i],nums[j],nums[k]] 满足 i!=j、i!=ki != j、i != ki!=ji!=kj!=kj != kj!=k ,同时还满足 nums[i]+nums[j]+nums[k]==0nums[i] + nums[j] + nums[k] == 0nums[i]+nums[j]+nums[k]==0 。请你返回所有和为 000 且不重复的三元组。
注意:答案中不可以包含重复的三元组。

例子

  1. 输入:nums=[−1,0,1,2,−1,−4]nums = [-1,0,1,2,-1,-4]nums=[1,0,1,2,1,4]
    输出:[[−1,−1,2],[−1,0,1]][[-1,-1,2],[-1,0,1]][[1,1,2],[1,0,1]]
    解释:
    nums[0]+nums[1]+nums[2]=(−1)+0+1=0。nums[0] + nums[1] + nums[2] = (-1) + 0 + 1 = 0。nums[0]+nums[1]+nums[2]=(1)+0+1=0
    nums[1]+nums[2]+nums[4]=0+1+(−1)=0。nums[1] + nums[2] + nums[4] = 0 + 1 + (-1) = 0。nums[1]+nums[2]+nums[4]=0+1+(1)=0
    nums[0]+nums[3]+nums[4]=(−1)+2+(−1)=0。nums[0] + nums[3] + nums[4] = (-1) + 2 + (-1) = 0。nums[0]+nums[3]+nums[4]=(1)+2+(1)=0
    不同的三元组是 [−1,0,1]和[−1,−1,2][-1,0,1] 和 [-1,-1,2][1,0,1][1,1,2]
    注意,输出的顺序和三元组的顺序并不重要。
  2. 输入:nums=[0,1,1]nums = [0,1,1]nums=[0,1,1]
    输出:[][][]
    解释:唯一可能的三元组和不为 000
  3. 输入:nums=[0,0,0]nums = [0,0,0]nums=[0,0,0]
    输出:[[0,0,0]][[0,0,0]][[0,0,0]]
    解释:唯一可能的三元组和为 000

思路

1. 暴力解法

虽然说暴力解法超时了,但大家会的思路基本上就是这个了,并且大部分人可能只会三重forforfor循环,但是并不知道之后怎么去进行去重。这里记录三种方法。

  • 时间复杂度O(n3)O(n^3)O(n3)
  • 空间复杂度:O(n)O(n)O(n)
class Solution:def threeSum(self, nums: List[int]) -> List[List[int]]:if not nums:return []result = []n = len(nums)for i in range(n-2):for j in range(i+1, n-1):for k in range(j+1, n):if nums[i] + nums[j] + nums[k] == 0:# 判断三元组中的元素是否相等,避免重复# 这种方法又暴力写法又复杂不建议使用if [nums[i], nums[j], nums[k]] not in result and [nums[i], nums[k], nums[j]] not in result \\and [nums[j], nums[i], nums[k]] not in result and [nums[j], nums[k], nums[i]] not in result \\and [nums[k], nums[i], nums[j]] not in result and [nums[k], nums[j], nums[i]] not in result:result.append([nums[i], nums[j], nums[k]])return result
class Solution:def threeSum(self, nums: List[int]) -> List[List[int]]:if not nums:return []result = []n = len(nums)for i in range(n-2):for j in range(i+1, n-1):for k in range(j+1, n):if nums[i] + nums[j] + nums[k] == 0:# 对三元组的元素进行排序实现去重triplet = sorted([nums[i], nums[j], nums[k]])if triplet not in result:result.append(triplet)return result
class Solution:def threeSum(self, nums: List[int]) -> List[List[int]]:n = len(nums)res = []nums.sort()  # 先对数组排序for i in range(n-2):if i > 0 and nums[i] == nums[i-1]:  # 避免重复计算continuefor j in range(i+1, n-1):if j > i + 1 and nums[j] == nums[j-1]:  # 避免重复计算continuefor k in range(j+1, n):if k > j + 1 and nums[k] == nums[k-1]:  # 避免重复计算continuetotal = nums[i] + nums[j] + nums[k]if total == 0:res.append([nums[i], nums[j], nums[k]])return res

2. 双指针➕排序

class Solution:def threeSum(self, nums):n = len(nums)nums.sort()ans = list()# 枚举 afor first in range(n):# 需要和上一次枚举的数不相同if first > 0 and nums[first] == nums[first - 1]:continue# c 对应的指针初始指向数组的最右端third = n - 1target = -nums[first]# 枚举 bfor second in range(first + 1, n):# 需要和上一次枚举的数不相同if second > first + 1 and nums[second] == nums[second - 1]:continue# 需要保证 b 的指针在 c 的指针的左侧while second < third and nums[second] + nums[third] > target:third -= 1# 如果指针重合,随着 b 后续的增加# 就不会有满足 a+b+c=0 并且 b<c 的 c 了,可以退出循环if second == third:breakif nums[second] + nums[third] == target:ans.append([nums[first], nums[second], nums[third]])return ans