给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?请你找出所有和为 0 且不重复的三元组。
示例:
输入:nums = [-1,0,1,2,-1,-4] 输出:[[-1,-1,2],[-1,0,1]] 输入:nums = [0] 输出:[]方法一:官方方法(排序+双指针)
对排序后的结果固定一个数,对剩下的数进行双指针找符合条件的值。
在这个思路上优化。
设固定的数为nums[a],若nums[a] > 0,则三数之和一定大于零,不符合条件结束循环。
当 nums[a] == nums[a - 1] 时,会产生重复的枚举,去重。例如:[1,1,2,3],固定nums[0]和nums[1],对剩下的双指针都会枚举到[1,2,3]这个数组,应该去重去掉。
同样nums[b]也是这样去重。
双指针和大于零,c左移。和小于零,b右移。这都比较容易处理了
public static List方法二:> threeSum(int[] nums) { int n = nums.length; Arrays.sort(nums); List
> ans = new ArrayList
>(); for (int a = 0; a < n; a++) { if (nums[a] > 0) { break; } //a和上一位数字一样结束此次循环,右移一位 if (a > 0 && nums[a] == nums[a - 1]) { continue; } int c = n - 1; //a固定 b、c双指针 for (int b = a + 1; b < n; b++) { //b和上一位数字一样结束此次循环,右移一位 if (b > a + 1 && nums[b] == nums[b - 1]) { continue; } //和大于零 c左移 while (b < c && nums[a] + nums[b] + nums[c] > 0) { c--; } //bc重合,指针重合 if (b == c) { break; } if (nums[a] + nums[b] + nums[c] == 0) { ArrayList
list = new ArrayList<>(); list.add(nums[a]); list.add(nums[b]); list.add(nums[c]); ans.add(list); } } } return ans; }
在官方基础上对nums[c] 也进行了去重处理,双指针用while更容易看和书写。
public static List总结:> threeSum1(int[] nums) { int n = nums.length; Arrays.sort(nums); List
> ans = new ArrayList
>(); for (int a = 0; a < n; a++) { //a和上一位数字一样结束此次循环,右移一位 if (a > 0 && nums[a] == nums[a - 1]) { continue; } int c = n - 1; int b = a + 1; // b、c双指针 while (b < c) { while (b > a + 1 && nums[b] == nums[b - 1]) { //不加这个条件可能会出现 b>=c的情况 if (b < c) { b++; continue; } } while (c > n - 1 && nums[c] == nums[c + 1] ) { if (b < c) { c--; continue; } } if (nums[a] + nums[b] + nums[c] == 0) { ArrayList
list = new ArrayList<>(); list.add(nums[a]); list.add(nums[b]); list.add(nums[c]); ans.add(list); //改变两边指针 b++; c--; } else if (nums[a] + nums[b] + nums[c] < 0) { //和小于零,左指针 右移动 b++; } else { //和大于零,右指针 左移动 c--; } } } return ans; }
方法都是排序+双指针就是双指针的处理不太一样。
这题不难理解,就是去重需要一些方法



