15. 3Sum
题目:
Given an array S of n integers, are there elements a, b, c in S such that a + b + c = 0? Find all unique triplets in the array which gives the sum of zero.
Note:
- Elements in a triplet (a,b,c) must be in non-descending order. (ie, a ≤ b ≤ c)
- The solution set must not contain duplicate triplets.
For example, given array S = {-1 0 1 2 -1 -4}, A solution set is: (-1, 0, 1) (-1, -1, 2)
链接: http://leetcode.com/problems/3sum/
题解:
3 pointers,注意处理重复的情况。
Time Complexity - O(n2), Space Complexity - O(1)
public class Solution { public ArrayList<ArrayList<Integer>> threeSum(int[] num) { ArrayList<ArrayList<Integer>> result = new ArrayList<ArrayList<Integer>>(); if(num.length < 3) return result; Arrays.sort(num); for(int start = 0; start < num.length - 2; start ++){ if(start > 0 && num[start] == num[start - 1]) continue; int left = start + 1, right = num.length - 1; while(left < right){ int sum = num[start] + num[left] + num[right]; if(sum == 0){ ArrayList<Integer> list = new ArrayList<Integer>(); list.add(num[start]); list.add(num[left]); list.add(num[right]); result.add(list); left ++; right --; while(left < right && num[left] == num[left - 1]) left ++; while(left < right && num[right] == num[right + 1]) right --; } else if (sum < 0){ left ++; } else { right --; } } } return result; } }
二刷:
为满足题意,先对数组进行排序。注意去重,去重的部分包括一个主指针i, 两个分指针lo以及hi,都要考虑。在加结果的时候,也可以使用Arrays.asList(num[i], num[lo], num[hi]),但之后这个list就是定长的,不可以再被增加了
Java:
Time Complexity - O(n2), Space Complexity - O(n)
public class Solution { public List<List<Integer>> threeSum(int[] nums) { List<List<Integer>> res = new ArrayList<>(); if (nums == null || nums.length < 3) { return res; } Arrays.sort(nums); for (int i = 0; i < nums.length - 2; i++) { if (i > 0 && nums[i] == nums[i - 1]) { continue; } int lo = i + 1; int hi = nums.length - 1; while (lo < hi) { int sum = nums[i] + nums[lo] + nums[hi]; if (sum == 0) { List<Integer> list = new ArrayList<>(); list.add(nums[i]); list.add(nums[lo]); list.add(nums[hi]); res.add(list); lo++; hi--; while (lo < hi && nums[lo] == nums[lo - 1]) { lo++; } while (lo < hi && nums[hi] == nums[hi + 1]) { hi--; } } else if (sum < 0) { lo++; } else { hi--; } } } return res; } }
Python:
class Solution(object): def threeSum(self, nums): """ :type nums: List[int] :rtype: List[List[int]] """ res = [] if not nums: return res nums.sort(); for i in range(0, len(nums) - 2): if i > 0 and nums[i] == nums[i - 1]: continue lo = i + 1 hi = len(nums) - 1 while lo < hi: sum = nums[i] + nums[lo] + nums[hi] if sum == 0: res.append([nums[i], nums[lo], nums[hi]]) lo += 1 hi -= 1 while lo < hi and nums[lo] == nums[lo - 1]: lo += 1 while lo < hi and nums[hi] == nums[hi + 1]: hi -= 1 elif sum < 0: lo += 1 else: hi -= 1 return res
三刷:
有两种思路。
1. 先排序再用双指针
2. 使用Two Sum的方法, 遍历 + HashMap
Java:
public class Solution { public List<List<Integer>> threeSum(int[] nums) { List<List<Integer>> res = new ArrayList<>(); if (nums == null) return res; Arrays.sort(nums); for (int i = 0; i < nums.length - 2; i++) { if (i > 0 && nums[i] == nums[i - 1]) continue; int lo = i + 1; int hi = nums.length - 1; while (lo < hi) { int sum = nums[i] + nums[lo] + nums[hi]; if (sum == 0) { List<Integer> list = new ArrayList<>(); list.add(nums[i]); list.add(nums[lo]); list.add(nums[hi]); res.add(list); lo++; hi--; while (lo < hi && nums[lo] == nums[lo - 1]) lo++; while (lo < hi && nums[hi] == nums[hi + 1]) hi--; } else if (sum < 0) { lo++; } else { hi--; } } } return res; } }
Reference:
https://leetcode.com/discuss/67914/easiest-java-solution
https://leetcode.com/discuss/23638/concise-o-n-2-java-solution