leetcode - 18.4Sum

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:**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:

  public List> fourSum(int[] nums, int target) {
        List> result = new ArrayList<>();
        if (nums == null || nums.length < 4) {
            return result;
        }

        Arrays.sort(nums);

        int max = nums[nums.length - 1];
        if (4 * max < target || 4 * nums[0] > target) {
            return result;
        }

        for (int i = 0; i < nums.length; i++) {
            int x = nums[i];
            if (i > 0 && x == nums[i - 1]) {
                continue;
            } else if (x + 3 * max < target) {
                continue;
            } else if (x + 3 * nums[0] > target) {
                break;
            } else if (x * 4 == target) {
                if (i + 3 < nums.length && nums[i + 3] == x) {
                    result.add(Arrays.asList(x, x, x, x));
                }
            } else {
                threeSum(nums, target - x, i + 1, result, x);
            }
        }

        return result;
    }

    private void threeSum(int[] nums, int target, int begin, List> result, int x1) {
        if (begin + 2 >= nums.length) {
            return;
        }

        int max = nums[nums.length - 1];
        if (3 * nums[begin] > target) {
            return;
        }

        for (int i = begin; i < nums.length; i++) {
            int x = nums[i];
            if (i > begin && x == nums[i - 1]) {
                continue;
            } else if (x + 2 * max < target) {
                continue;
            } else if (x + 2 * nums[begin] > target) {
                break;
            } else if (x * 3 == target) {
                if (i + 2 < nums.length && nums[i + 2] == x) {
                    result.add(Arrays.asList(x1, x, x, x));
                }
            } else {
                twoSum(nums, target - x, i + 1, result, x1, x);
            }
        }
    }

    private void twoSum(int[] nums, int target, int begin, List> result, int x1, int x2) {
        if (begin + 1 >= nums.length) {
            return;
        }

        if (2 * nums[begin] > target) {
            return;
        }

        int i = begin, j = nums.length - 1, sum, k;
        while (i < j) {
            sum = nums[i] + nums[j];
            if (sum == target) {
                result.add(Arrays.asList(x1, x2, nums[i], nums[j]));

                k = nums[i];
                while (++i < j && k == nums[i])
                    ;
                k = nums[j];
                while (i < --j && k == nums[j])
                    ;

            } else if (sum > target) {
                j--;

            } else {
                i++;
            }
        }
        return;
    }

你可能感兴趣的:(leetcode题集)