package com.interview.array;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
/**
* Date 07/31/2016
* @author Tushar Roy
*
* 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.
*
* Time complexity O(n^3)
* Space complexity O(1)
*
* Reference
* https://leetcode.com/problems/4sum/
*/
public class FourSum {
public List<List<Integer>> fourSum(int[] nums, int target) {
if (nums.length < 4) {
return Collections.EMPTY_LIST;
}
Arrays.sort(nums);
List<List<Integer>> result = new ArrayList<>();
for (int i = 0; i < nums.length - 3; i++) {
if (i != 0 && nums[i] == nums[i - 1]) {
continue;
}
if(nums[i] + nums[i+1] + nums[i+2] + nums[i+3] > target) {
break;
}
if(nums[i] + nums[nums.length - 3] + nums[nums.length - 2] + nums[nums.length - 1] < target) {
continue;
}
for (int j = i + 1; j < nums.length - 2; j++) {
if (j != i + 1 && nums[j] == nums[j - 1]) {
continue;
}
if (nums[i] + nums[j] + nums[j + 1] + nums[j + 2] > target) {
break;
}
if (nums[i] + nums[j] + nums[nums.length - 1] + nums[nums.length - 1] < target) {
continue;
}
int low = j + 1;
int high = nums.length - 1;
while (low < high) {
if (low != j + 1 && nums[low] == nums[low - 1]) {
low++;
continue;
}
if (high != nums.length - 1 && nums[high] == nums[high + 1]) {
high--;
continue;
}
int sum = nums[i] + nums[j] + nums[low] + nums[high];
if (sum == target) {
List<Integer> r = new ArrayList<>();
r.add(nums[i]);
r.add(nums[j]);
r.add(nums[low]);
r.add(nums[high]);
result.add(r);
low++;
high--;
} else if (sum < target) {
low++;
} else {
high--;
}
}
}
}
return result;
}
public static void main(String args[]) {
int[] nums = {1, 1, 4, 5, 9, 11};
int[] nums1 = {1, 0, -1, 0, -2, 2};
int target = 0;
FourSum fourSum = new FourSum();
List<List<Integer>> result = fourSum.fourSum(nums1, target);
result.forEach(System.out::print);
}
}