2-Sum
首先对数组排序,两个指针分别从头尾开始根据和与0比较的大小相向游动,而不是固定其中一个另一个由中位数双向游动
int lo = i+1, hi = nums.length-1, sum = 0;
while (lo < hi) {
if (nums[lo] + nums[hi] == sum) {
res.add(Arrays.asList(nums[i], nums[lo], nums[hi]));
/* conclude same elements */
while (lo < hi && nums[lo] == nums[++lo]) ;
while (lo < hi && nums[hi] == nums[--hi]) ;
}
else if (nums[lo] + nums[hi] < sum)
lo++;
else hi--;
}
3-Sum
固定其中一个值( 0 - lenth-2 ),剩余两个同理2-Sum,而不是固定其中两个剩余一个从中位数开始双向游动;
Arrays.sort(nums);
for (int i = 0; i < nums.length - 2; i++){ // fix the first element
if ( i == 0 || (i > 0 && nums[i] != nums[i-1])){ // conclude same elements
int lo = i+1, hi = nums.length-1, sum = 0 - nums[i];
/* same as 2-Sum */
}
}
K-Sum
public List<List<Integer>> kSum(int[] nums, int target, int start, int k) {
List<List<Integer>> res = new ArrayList<>();
if (start == nums.length || nums[start] * k > target || target > nums[nums.length - 1] * k)
return res;
if (k == 2)
return twoSum(nums, target, start);
for (int i = start; i < nums.length; ++i)
if (i == start || nums[i - 1] != nums[i])
for (var set : kSum(nums, target - nums[i], i + 1, k - 1)) {
res.add(new ArrayList<>(Arrays.asList(nums[i])));
res.get(res.size() - 1).addAll(set);
}
return res;
}
public List<List<Integer>> twoSum(int[] nums, int target, int start) {
List<List<Integer>> res = new ArrayList<>();
int lo = start, hi = nums.length - 1;
while (lo < hi) {
int sum = nums[lo] + nums[hi];
if (sum < target || (lo > start && nums[lo] == nums[lo - 1]))
++lo;
else if (sum > target || (hi < nums.length - 1 && nums[hi] == nums[hi + 1]))
--hi;
else
res.add(Arrays.asList(nums[lo++], nums[hi--]));
}
return res;
}