给你一个包含 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
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/3sum
# 三数之和为0 class Solution: def threeSum(self, nums: [int]) -> [int]: """ 先排序,再用双指针,排序O(nlogn),寻找二三个数O(n),寻找一二三个数O(n^2),所以时间O(n),空间O(logn) 思路:整形数组,先排序,利于后面寻找三个数,每轮搜索,固定第一个数,第二个数右移,第三个数左移,比较和与target 算法流程: 1.排序数组,初始化返回数组ans [] 2.遍历数组,检查当前的first指向元素是否大于0,成立则break,不可能有a+b+c=0成立,检查first是大于0即第二个数的first开始, 且与前一个元素值相同,继续下一个first 3.每次遍历寻找第一个数时,初始化third为最后一个元素,第一个元素值的相反数即为搜索本次二三个数和的目标值target 4.再次遍历数组,从first+1开始,检查second和second-1对应元素值是否相等,等则continue,继续寻找second 5.当second<third且和大于target时,由于排序,此时只有减小和才可能等于target,即third--, 重复移动third寻找合适的third,当second=third或和<=target时,break当前的while循环 6.上步break, 检查second==third, 成立则break second third,应该更新first,继续2 3 4 5 6 7.5步的while循环仅second=third或和等于小于target时break, 如果和等target则将此三个数append进ans, 如果不等target,其实就是和小于target, 即继续更新second, 重复4 5 6 7步 8.重复2-7,直到break或遍历完数组,返回ans :param nums: :return: """ nums.sort() # 为便于后面寻找,先排序 n = len(nums) ans = [] # 初始化返回数组 for first in range(n): if nums[first] > 0: # 由于数组已经排序,只要第一个数大于0,后面的数肯定都大于0,不可能出现a+b+c=0,直接break,就不用再去寻找后面的可能性 break if first > 0 and nums[first] == nums[first-1]: # 第一个数在遍历到第二及以后的数时,检查是否与前一个数重复,是则continue,否则继续寻找二三个数 continue third = n -1 # 每次更新第一个数时,third指向最后一个数 target = -nums[first] # target对第一个数取反,后面的二三个数,只需要考虑其和与target的比较,每次更新第一个数的时候,更新target for second in range(first+1, n): # 第二个数与上次遍历相同,继续遍历,寻找第二个数 if second > first + 1 and nums[second] == nums[second-1]: continue # 左指针在右指针左侧,且和大于target while second < third and nums[second] + nums[third] > target: # 由于是排序数组,大概率应该是其和小于target的,只有当左指针在右指针左边,且和大于target,左移右指针third--,更新third third -= 1 # 左右指针重合或左右指针数和小于等于target if second == third: # 大概率是和小于target,此时应该更新second,和才会变大,检查左右指针是否相等,如果等,即二三数为同一个数,必须break break if nums[second] + nums[third] == target: # 检查二三数和是否等于target, 成立则append进ans,继续更新second ans.append([nums[first], nums[second], nums[third]]) return ans if __name__ == "__main__": nums = [2,6,7,-8,3,4,2,-13,3,-5] nums1 = [] nums2 = [0] nums3 = [1,2] test = Solution() print(test.threeSum(nums)) # [[-13, 6, 7], [-8, 2, 6], [-5, 2, 3]] print(test.threeSum(nums1)) # [] print(test.threeSum(nums2)) # [] print(test.threeSum(nums3)) # []
package main import ( "fmt" "sort" ) func main() { nums := []int{2, 6, 7, -8, 3, 4, 2, -13, 3, -5} fmt.Println(threeSum(nums)) } // 排序+双指针 func threeSum(nums []int) [][]int { sort.Ints(nums) n := len(nums) ans := [][]int{} var first int for first = 0; first < n; first++ { if nums[first] > 0 { break } if first > 0 && nums[first] == nums[first-1] { continue } third := n - 1 target := -nums[first] for second := first + 1; second < n-1; second++ { if second > first+1 && nums[second] == nums[second-1] { continue } for second < third && nums[second]+nums[third] > target { third-- } if second == third { break } if nums[second]+nums[third] == target { ans = append(ans, []int{nums[first], nums[second], nums[third]}) } } } return ans }