基础数据结构之数组的双指针技巧之对撞指针(两端向中间):三数之和(LeetCode 15 中等题)
**题目:**给你一个整数数组 nums ,判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i != j、i != k 且 j != k ,同时还满足 nums[i] + nums[j] + nums[k] == 0 。请你返回所有和为 0 且不重复的三元组。
**解题思路:**三层循环暴力法会得到重复结果,所以需要先排序去除重复。
双指针对撞也需要先排序,之后先固定一个初始值,之后需要俩数字和初始值结合起来为0,俩数字如何选择?可以通过第一个数字和最后一个数字加起来看跟目标值的对比,大了说明需要变小一点,那就移动大数那边的指针,否则,就移动小数那边的指针。其中,边界条件需要考虑:初始值一致或者双指针对应的俩数字跟相邻数字一致的话都会导致出现重复结果,需要进行排除。
class Solution:def threeSum(self, nums: List[int]) -> List[List[int]]:# 预处理:先排序,避免三个值一致但顺序不同的情况出现nums.sort()result = []n = len(nums)for i in range(0,n-2):# 边界处理:i值一样的也需要跳过(已经处理过则跳过)if nums[i] == nums[i-1] and i > 0:continue# 先确定一个数,剩下两个数分别头尾指针开始对撞。根据和的大小决定哪个指针移动j = i + 1k = n - 1while j < k:target = nums[i]+nums[j]+nums[k]if target == 0:result.append([nums[i],nums[j],nums[k]])# 边界处理:j、k两侧一致的元素需要跳过(已经处理过则跳过)while j < k and nums[j] == nums[j+1]:j+=1while j < k and nums[k] == nums[k-1]:k-=1# 同时移动前需要排除大小一致的元素,避免结果重复j+=1k-=1elif j < k and target<0:j+=1elif j < k and target>0:k-=1return result
