一. 题目
-
题目
给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?请你找出所有满足条件且不重复的三元组。注意:答案中不可以包含重复的三元组。
-
示例
二. 方法一: 暴力法(超时)
-
解题思路
-
解题代码
def threeSum(self, nums: List[int]) -> List[List[int]]: result = [] nums.sort() size = len(nums) for i in range(size - 2): for j in range(i + 1, size - 1): for k in range(j + 1, size): if nums[i] + nums[j] + nums[k] == 0: temp = [nums[i], nums[j], nums[k]] if temp not in result: result.append(temp) return result
-
分析
时间复杂度: O(n^3)
空间复杂度: O(n^2)
三. 方法二: 双指针法
-
解题思路
- 遍历列表中的所有元素, 如果当前元素(index)和前一个元素相等, 则跳过后续的操作
- 定义两个指针, 分别指向当前位置右侧元素的一个(left)和最后一个元素(right)
- 如果这三个元素和为0, 则将这中情况插入都列表中
- 如果 left指向的下一个元素等于当前元素, 则直接跳过
- 如果right指向的前一个元素等于当前元素, 则直接跳过
- left 向后移动一位, right向前移动一位
- 如果这三个元素和大于0, 则right向前移动一位
- 如果这三个元素和小于0, 则index向后移动一位
-
解题代码
def threeSum(self, nums: List[int]) -> List[List[int]]: size = len(nums) result = [] # 如果列表为空 或 列表长度小于3, 则直接返回[] if not nums or size < 3: return [] # 对了列表进行排序 nums.sort() for i in range(size): # 如果最左边的元素都大于0, 则三数之和一定大于0 if nums[i] > 0: return result # 如果当前元素等于上一个元素, 则跳过此循环 # 因为所有满足的情况在上一轮已经找到了 if i > 0 and nums[i] == nums[i - 1]: continue # 定义2个指针, 分别指向当前元素右边的第一个元素和最后一个元素 left = i + 1 right = size - 1 while left < right: # 如果当前3数之和等于0, 则将当前情况添加到列表中 if nums[i] + nums[left] + nums[right] == 0: result.append([nums[i], nums[left], nums[right]]) # 如果左指针当前元素 和 下一个元素相等 # 则左指针向后移动一位 while left < right and nums[left] == nums[left + 1]: left += 1 # 如果右指针当前元素 和 前一个元素相等 # 则右指针向前移动一位 while left < right and nums[right] == nums[right - 1]: right -= 1 # 此时再将左右指针分贝向后移动和向前移动 left += 1 right -= 1 # 如果当前三个元素和大于0, 则右指针向前移动 elif nums[i] + nums[left] + nums[right] > 0: right -= 1 # 如果当前三个元素和小于0, 则左指针向后移动 else: left += 1 return result
-
分析
时间复杂度: O(n^2)