15. 三数之和
一、题目描述
给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?请你找出所有和为 0 且不重复的三元组。
注意:答案中不可以包含重复的三元组。
- 0 <= nums.length <= 3000
- -105 <= nums[i] <= 105
二、解题思路
3个数,如果直接使用3层循环的话,估计应该会超时,所以只能想其他办法。
a + b + c = 0
可以转成 b + c = -a
,那么就相当于查找2数之和,这个就变得简单了
3元组去重的问题:
- 通过排序,保证每次的 a、b 不一样,那么 c 肯定不同,3元组也就不一样了
至于进一步的优化:
- 既然3个数相加等于0,那么肯定有一个数是非正数
- 对数组进行排序后,保证最小的那个数是非正数就行
三、复杂度分析
四、参考代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57
|
private List<List<Integer>> threeSum(int[] nums) { List<List<Integer>> result = new ArrayList<>(); if (nums.length < 3) { return result; } Arrays.sort(nums); if (nums[0] > 0 || nums[nums.length - 1] < 0) { return result; } for (int i = 0; i < nums.length && nums[i] <= 0; i++) { List<List<Integer>> sumList = twoSum(nums, -nums[i], i + 1, nums.length - 1); if (sumList.size() > 0) { result.addAll(sumList); } while (i < nums.length - 1 && nums[i] == nums[i + 1]) { i++; } } return result; }
private List<List<Integer>> twoSum(int[] nums, int sum, int start, int end) { List<List<Integer>> result = new ArrayList<>(); int lp = start, rp = end; while (lp < rp) { int temp = nums[lp] + nums[rp]; if (temp == sum) { List<Integer> sumList = new ArrayList<>(3); sumList.add(-sum); sumList.add(nums[lp]); sumList.add(nums[rp]); result.add(sumList); while (lp < rp && nums[lp] == nums[++lp]); while (lp < rp && nums[rp] == nums[--rp]); } else if (temp < sum) { lp++; } else { rp--; } } return result; }
|