18. 4Sum (Medium)

Given an arraySofnintegers, are there elementsa,b,c, anddinSsuch thata+b+c+d= target? Find all unique quadruplets in the array which gives the sum of target.

Note: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 1: sort O(n^3); O(1)
    public List<List<Integer>> fourSum(int[] num, int target) {
        List<List<Integer>> rst = new ArrayList<>();
        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;
                int right = num.length - 1;
                while (left < right) {
                    int sum = num[i] + num[j] + num[left] + num[right];
                    if (sum < target) {
                        left++;
                    } else if (sum > target) {
                        right--;
                    } else {
                        ArrayList<Integer> tmp = new ArrayList<>();
                        tmp.add(num[i]);
                        tmp.add(num[j]);
                        tmp.add(num[left]);
                        tmp.add(num[right]);
                        rst.add(tmp);
                        left++;
                        right--;
                        while (left < right && num[left] == num[left - 1]) {
                            left++;
                        }
                        while (left < right && num[right] == num[right + 1]) {
                            right--;
                        }
                    }
                }
            }
        }

        return rst;
    }
Solution 2: O(n^2); O(n^2)待定
    public List<List<Integer>> fourSum(int[] num, int target) {
        Arrays.sort(num);

        // for holding visited pair sums. All pairs with the same pair sum are grouped together
        Map<Integer, List<int[]>> twoSumMap = new HashMap<>(); 
        Set<List<Integer>> res = new HashSet<>(); // for holding the results

        for (int i = 0; i < num.length; i++) {
// get rid of repeated pair sums
            if (i > 1 && num[i] == num[i - 2]) continue;

            for (int j = i + 1; j < num.length; j++) {
// get rid of repeated pair sums
                if (j > i + 2 && num[j] == num[j - 2]) continue;

// for each pair sum, check if the pair sum that is needed to get the target has been visited.
                if (twoSumMap.containsKey(target - (num[i] + num[j]))) {
// if so, get all the pairs that contribute to this visited pair sum.
                    List<int[]> ls = twoSumMap.get(target - (num[i] + num[j]));

                    for (int[] pair : ls) {
// we have two pairs: one is indicated as (pair[0], pair[1]), the other is (i, j).
// we first need to check if they are overlapping with each other.
                        int m1 = Math.min(pair[0], i); // m1 will always be the smallest index
                        int m2 = Math.min(pair[1], j); // m2 will be one of the middle two indices
                        int m3 = Math.max(pair[0], i); // m3 will be one of the middle two indices
                        int m4 = Math.max(pair[1], j); // m4 will always be the largest index
                        if (m1 == m3 || m1 == m4 || m2 == m3 || m2 == m4)
                            continue; // two pairs are overlapping, so just ignore this case
                        // else record the result
                        res.add(Arrays.asList(num[m1], num[Math.min(m2, m3)], num[Math.max(m2, m3)], num[m4])); 
                    }
                }

// mark that we have visited current pair and add it to the corrsponding pair sum group.
// here we've encoded the pair indices i and j into an integer array of length 2.
                twoSumMap.computeIfAbsent(num[i] + num[j], key -> new ArrayList<>()).add(new int[]{i, j});
            }
        }

        return new ArrayList<List<Integer>>(res);
    }

results matching ""

    No results matching ""