18. 4Sum
题目:
Given an array S of n integers, are there elements a, b, c, and d in S such that a + b + c + d = target? Find all unique quadruplets in the array which gives the sum of target.
Note:
- Elements in a quadruplet (a,b,c,d) must be in non-descending order. (ie, a ≤ b ≤ c ≤ d)
- The solution set must not contain duplicate quadruplets.
For example, given array S = {1 0 -1 0 -2 2}, and target = 0. A solution set is: (-1, 0, 0, 1) (-2, -1, 1, 2) (-2, 0, 0, 2)
链接:http://leetcode.com/problems/4sum/
题解:
同3Sum。 Time Complexity - O(n3), Space Complexity - O(1)
public class Solution { public ArrayList<ArrayList<Integer>> fourSum(int[] num, int target) { ArrayList<ArrayList<Integer>> result = new ArrayList<ArrayList<Integer>>(); if(num == null || num.length < 4) return result; Arrays.sort(num); for(int i = 0; i < num.length - 3; i ++){ if(i > 0 && num[i] == num[i - 1]) continue; for(int j = i + 1; j < num.length - 2; j ++){ if(j > i + 1 && num[j] == num[j - 1]) continue; int left = j + 1, right = num.length - 1; while(left < right){ int sum = num[i] + num[j] + num[left] + num[right]; if(sum == target){ ArrayList<Integer> list = new ArrayList<Integer>(); list.add(num[i]); list.add(num[j]); 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 < target) { left ++; } else { right--; } } } }
return result; } }
二刷:
根3Sum方法一样,也是重点在去重复。应该还可以做一些pruning来继续优化速度
Time Complexity - O(n3), Space Complexity - O(1)
Java:
public class Solution { public List<List<Integer>> fourSum(int[] nums, int target) { List<List<Integer>> res = new ArrayList<>(); if (nums == null || nums.length < 4) { return res; } Arrays.sort(nums); for (int i = 0; i < nums.length - 3; i++) { if (i > 0 && nums[i] == nums[i - 1]) { continue; } for (int j = i + 1; j < nums.length - 2; j++) { if (j > i + 1 && nums[j] == nums[j - 1]) { continue; } int lo = j + 1, hi = nums.length - 1; while (lo < hi) { int sum = nums[i] + nums[j] + nums[lo] + nums[hi]; if (sum == target) { List<Integer> list = new ArrayList<>(); list.add(nums[i]); list.add(nums[j]); 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 < target) { lo++; } else { hi--; } } } } return res; } }
Python:
有很多其他方法可以优化,需要更深入学习Python
class Solution(object): def fourSum(self, nums, target): """ :type nums: List[int] :type target: int :rtype: List[List[int]] """ if not nums or len(nums) < 4: return [] res = [] nums.sort() for i in range(0, len(nums) - 3): if i > 0 and nums[i] == nums[i - 1]: continue for j in range(i + 1, len(nums) - 2): if j > i + 1 and nums[j] == nums[j - 1]: continue lo = j + 1 hi = len(nums) - 1 while lo < hi: sum = nums[i] + nums[j] + nums[lo] + nums[hi] if sum == target: res.append([nums[i], nums[j], 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 < target: lo += 1 else: hi -= 1 return res
三刷:
使用旧的方法。速度不是很快。 这道题虽然可以不动脑子,用3Sum的方法来做,但仔细想一想应该有很多地方可以剪枝。
在reference里放了一些Discuss区比较快的代码链接。
Java:
Time Complexity - O(n3), Space Complexity - O(1)
public class Solution { public List<List<Integer>> fourSum(int[] nums, int target) { List<List<Integer>> res = new ArrayList<>(); if (nums == null || nums.length < 4) return res; Arrays.sort(nums); for (int i = 0; i < nums.length - 3; i++) { if (i > 0 && nums[i] == nums[i - 1]) continue; for (int j = i + 1; j < nums.length - 2; j++) { if (j > i + 1 && nums[j] == nums[j - 1]) continue; int lo = j + 1, hi = nums.length - 1; while (lo < hi) { int sum = nums[i] + nums[j] + nums[lo] + nums[hi]; if (sum == target) { List<Integer> list = new ArrayList<>(); list.add(nums[i]); list.add(nums[j]); 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 < target) { lo++; } else { hi--; } } } } return res; } }
Reference:
https://leetcode.com/discuss/69517/7ms-java-code-win-over-100%25
https://leetcode.com/discuss/54724/python-140ms-beats-100%25-and-works-for-n-sum-n-2
https://leetcode.com/discuss/77704/java-backtracking-solution-for-k-sum-beat-94%25
https://leetcode.com/discuss/28936/a-conise-python-solution-based-on-ksum
https://leetcode.com/discuss/78276/java-little-bit-faster-than-other-common-methods-9ms-beats-95%25
https://leetcode.com/discuss/29867/share-my-python-code-run-time-200-20ms
http://stackoverflow.com/questions/16748030/difference-between-arrays-aslistarray-vs-new-arraylistintegerarrays-aslist
https://leetcode.com/discuss/33667/average-and-worst-case-java-solution-by-reducing-4sum-to-2sum