友情支持

如果您觉得这个笔记对您有所帮助,看在D瓜哥码这么多字的辛苦上,请友情支持一下,D瓜哥感激不尽,😜

支付宝

微信

有些打赏的朋友希望可以加个好友,欢迎关注D 瓜哥的微信公众号,这样就可以通过公众号的回复直接给我发信息。

wx jikerizhi

公众号的微信号是: jikerizhi因为众所周知的原因,有时图片加载不出来。 如果图片加载不出来可以直接通过搜索微信号来查找我的公众号。

18. 4Sum

Given an array nums of n integers and an integer target, are there elements a, b, c, and d in nums 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.

Example:

Given array nums = [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]
]

思路分析

  • 一刷

  • 二刷

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
/**
 * Runtime: 4 ms, faster than 94.46% of Java online submissions for 4Sum.
 *
 * Memory Usage: 40.7 MB, less than 52.17% of Java online submissions for 4Sum.
 */
public List<List<Integer>> fourSum(int[] nums, int target) {
    int numCount = 4;
    if (Objects.isNull(nums) || nums.length < numCount) {
        return Collections.emptyList();
    }

    Arrays.sort(nums);
    int length = nums.length;
    if (target < numCount * nums[0] || numCount * nums[length - 1] < target) {
        return Collections.emptyList();
    }

    List<List<Integer>> result = new LinkedList<>();
    for (int i = 0; i < length - 3; i++) {
        if (i > 0 && nums[i] == nums[i - 1]) {
            continue;
        }
        for (int j = i + 1; j < length - 2; j++) {
            if (j > i + 1 && nums[j] == nums[j - 1]) {
                continue;
            }
            int twoSumTarget = target - nums[i] - nums[j];
            int minTwoSum = nums[j + 1] + nums[j + 2];
            int maxTwoSum = nums[length - 1] + nums[length - 2];
            if (twoSumTarget < minTwoSum || maxTwoSum < twoSumTarget) {
                continue;
            }
            for (int m = j + 1, n = length - 1; m < n; ) {
                int twoSum = nums[m] + nums[n];
                if (twoSum < twoSumTarget) {
                    while (m < n && nums[m] == nums[m + 1]) {
                        m++;
                    }
                    m++;
                } else if (twoSumTarget < twoSum) {
                    while (m < n && nums[n - 1] == nums[n]) {
                        n--;
                    }
                    n--;
                } else {
                    result.add(Arrays.asList(nums[i], nums[j], nums[m], nums[n]));

                    while (m < n && nums[m] == nums[m + 1]) {
                        m++;
                    }
                    m++;

                    while (m < n && nums[n - 1] == nums[n]) {
                        n--;
                    }
                    n--;
                }
            }
        }
    }

    return result;
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
/**
 * @author D瓜哥 · https://www.diguage.com
 * @since 2024-08-15 18:37:58
 */
public List<List<Integer>> fourSum(int[] nums, int target) {
  if (nums == null || nums.length < 4) {
    return Collections.emptyList();
  }
  Arrays.sort(nums);
  return numSum(nums, 0, 4, target);
}

private List<List<Integer>> numSum(int[] nums, int idx, int cnt, long target) {
  // 剩余长度不够,则直接返回
  if (nums.length - idx < cnt || cnt < 2) {
    return new ArrayList<>();
  }
  List<List<Integer>> result = new ArrayList<>();
  if (cnt == 2) {
    int l = idx;
    int r = nums.length - 1;
    while (l < r) {
      int sum = nums[l] + nums[r];
      int left = nums[l];
      int right = nums[r];
      if (sum < target) {
        while (l < r && nums[l] == left) {
          l++;
        }
      } else if (target < sum) {
        while (l < r && nums[r] == right) {
          r--;
        }
      } else {
        result.add(new ArrayList<>(Arrays.asList(left, right)));
        while (l < r && nums[l] == left) {
          l++;
        }
        while (l < r && nums[r] == right) {
          r--;
        }
      }
    }
  } else {
    for (int i = idx; i < nums.length; i++) {
      int num = nums[i];
      List<List<Integer>> temp = numSum(nums, i + 1, cnt - 1, target - num);
      for (List<Integer> rs : temp) {
        rs.addFirst(num);
        result.add(rs);
      }
      while (i < nums.length - 1 && nums[i] == nums[i + 1]) {
        i++;
      }
    }
  }
  return result;
}