[LeetCode] 15. 3Sum
Given an integer array nums, return all the triplets [nums[i], nums[j], nums[k]]
such that i != j
, i != k
, and j != k
, and nums[i] + nums[j] + nums[k] == 0
.
Notice that the solution set must not contain duplicate triplets.
Example 1:
Input: nums = [-1,0,1,2,-1,-4] Output: [[-1,-1,2],[-1,0,1]]
Example 2:
Input: nums = [] Output: []
Example 3:
Input: nums = [0] Output: []
Constraints:
0 <= nums.length <= 3000
-105 <= nums[i] <= 105
三数之和。
给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?请你找出所有和为 0 且不重复的三元组。
注意:答案中不可以包含重复的三元组。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/3sum
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
题意是给一个数组,请问是否能找到这样的组合使得 a + b + c = 0?输出所有这样的 [a, b, c] 组合。
还是 two sum 的思路,双指针从两边往中间逼近。因为和是 0,所以可以先固定a的位置,然后找是否有 b + c = 0 - a 的组合。首先需要对数组排序,然后在执行过程中需要排除一些重复数字,避免最后的 output 有重复。同时,在遍历a的范围的时候,如果 a > 0 就可以直接跳过了,因为数组是排序过的,如果 a 大于 0,b,c 也必定大于0。
时间O(n^2)
空间O(n^2) - list of list
JavaScript实现
1 /** 2 * @param {number[]} nums 3 * @return {number[][]} 4 */ 5 var threeSum = function(nums) { 6 const res = []; 7 let left, right, sum; 8 nums.sort((a, b) => a - b); 9 for (let i = 0; i < nums.length - 2; i++) { 10 if (nums[i] > 0) break; 11 if (nums[i] === nums[i - 1]) continue; 12 left = i + 1; 13 right = nums.length - 1; 14 sum = 0 - nums[i]; 15 while (left < right) { 16 if (nums[left] + nums[right] === sum) { 17 res.push([nums[i], nums[left], nums[right]]); 18 while (left < right && nums[left] === nums[left + 1]) { 19 left++; 20 } 21 while (left < right && nums[right] === nums[right - 1]) { 22 right--; 23 } 24 left++; 25 right--; 26 } else if (nums[left] + nums[right] < sum) { 27 left++; 28 } else { 29 right--; 30 } 31 } 32 } 33 return res; 34 };
Java实现
1 class Solution { 2 public List<List<Integer>> threeSum(int[] nums) { 3 List<List<Integer>> res = new ArrayList<>(); 4 // corner case 5 if (nums == null || nums.length == 0) { 6 return res; 7 } 8 9 // normal case 10 Arrays.sort(nums); 11 for (int i = 0; i < nums.length - 2; i++) { 12 // 对于一个排过序的数组,如果nums[i] > 0了,说明已经在数组的右半部分了 13 if (nums[i] > 0) { 14 break; 15 } 16 // 跳过重复数字 17 if (i > 0 && nums[i] == nums[i - 1]) { 18 continue; 19 } 20 int low = i + 1; 21 int hi = nums.length - 1; 22 int sum = 0 - nums[i]; 23 while (low < hi) { 24 if (nums[low] + nums[hi] == sum) { 25 res.add(Arrays.asList(nums[i], nums[low], nums[hi])); 26 while (low < hi && nums[low] == nums[low + 1]) { 27 low++; 28 } 29 while (low < hi && nums[hi] == nums[hi - 1]) { 30 hi--; 31 } 32 low++; 33 hi--; 34 } else if (nums[low] + nums[hi] < sum) { 35 low++; 36 } else { 37 hi--; 38 } 39 } 40 } 41 return res; 42 } 43 }
python3实现
1 class Solution: 2 def threeSum(self, nums: List[int]) -> List[List[int]]: 3 res = [] 4 n = len(nums) 5 if (not nums or n < 3): 6 return res 7 8 nums.sort() 9 for i in range(n): 10 if (nums[i] > 0): 11 return res 12 if (i > 0 and nums[i] == nums[i - 1]): 13 continue 14 lo = i + 1 15 hi = n - 1 16 while (lo < hi): 17 if (nums[i] + nums[lo] + nums[hi] == 0): 18 res.append([nums[i], nums[lo], nums[hi]]) 19 while (lo < hi and nums[lo] == nums[lo + 1]): 20 lo = lo + 1 21 while (lo < hi and nums[hi] == nums[hi - 1]): 22 hi = hi - 1 23 lo = lo + 1 24 hi = hi - 1 25 elif(nums[i] + nums[lo] + nums[hi] > 0): 26 hi = hi - 1 27 else: 28 lo = lo + 1 29 return res