Tuesday, September 15, 2015

4Sum | Leetcode

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, abcd)
  • 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)
---

Solution: This is almost the same problem as 3Sum. For each element i, merge the answer with the 3Sum of elements i+1 to the end of the array.
public class Solution {
    public List<List<Integer>> fourSum(int[] nums, int target) {
        Arrays.sort(nums);

        List<List<Integer>> answer = new ArrayList<>();

        for (int i = 0; i < nums.length - 3; i++) {
            // Avoid duplicates.
            if (i > 0 && nums[i] == nums[i - 1]) continue;
            
            List<List<Integer>> threeSums = threeSum(nums, i + 1, target - nums[i]);
            if (threeSums.isEmpty()) continue;
            
            for (List<Integer> list: threeSums) {
                List<Integer> tempList = new ArrayList<>();
                tempList.add(nums[i]);
                tempList.addAll(list);
                answer.add(tempList);
            }
        }
        
        return answer;
    }
    
    public List<List<Integer>> threeSum(int[] nums, int startIndex, int target) {
        List<List<Integer>> answer = new ArrayList<>();
        
        for (int i = startIndex; i < nums.length - 2; i++) {
            // Avoid duplicates.
            if (i > startIndex && nums[i] == nums[i - 1]) continue;
            
            int curTarget = target - nums[i];
            int first = i + 1;
            int last = nums.length - 1;
            
            while (first < last) {
                int sum = nums[first] + nums[last];
                
                if (sum == curTarget) {
                    answer.add(Arrays.asList(nums[i], nums[first], nums[last]));
                    first++;
                    last--;
                    
                    // Avoid duplicates.
                    while (first < last && nums[first] == nums[first - 1]) first++;
                    while (first < last && nums[last] == nums[last + 1]) last--;
                } else if (sum > curTarget) {
                    last--;
                } else {
                    first++;
                }
            }
        }
        
        return answer;
    }
}

No comments: