leetcode
leetcode 2851 ~ 2900
数对和

数对和

难度:

标签:

题目描述

Design an algorithm to find all pairs of integers within an array which sum to a specified value.

Example 1:

Input: nums = [5,6,5], target = 11
Output: [[5,6]]

Example 2:

Input: nums = [5,6,5,6], target = 11
Output: [[5,6],[5,6]]

Note:

  • nums.length <= 100000
  • -10^5 <= nums[i], target <= 10^5

代码结果

运行时间: 82 ms, 内存: 36.1 MB


/*
 * 思路:
 * 1. 使用Java Stream API来简化处理。
 * 2. 使用Collectors.groupingBy来对数组中的数值进行分组和计数。
 * 3. 使用Stream和Map来遍历数组,找到所有满足条件的数对。
 * 4. 返回数对列表。
 */
import java.util.*;
import java.util.stream.*;

public class TwoSumPairsStream {
    public static List<int[]> findPairs(int[] nums, int target) {
        Map<Integer, Long> map = Arrays.stream(nums).boxed()
            .collect(Collectors.groupingBy(e -> e, Collectors.counting()));

        List<int[]> result = new ArrayList<>();

        Arrays.stream(nums).forEach(num -> {
            int complement = target - num;
            if (map.getOrDefault(complement, 0L) > 0 && map.getOrDefault(num, 0L) > 0) {
                if (num == complement && map.get(num) < 2) return;
                result.add(new int[]{num, complement});
                map.put(complement, map.get(complement) - 1);
                map.put(num, map.get(num) - 1);
            }
        });

        return result.stream().filter(pair -> pair[0] <= pair[1]).collect(Collectors.toList());
    }

    public static void main(String[] args) {
        int[] nums1 = {5, 6, 5};
        int target1 = 11;
        int[] nums2 = {5, 6, 5, 6};
        int target2 = 11;

        System.out.println(Arrays.deepToString(findPairs(nums1, target1).toArray()));
        System.out.println(Arrays.deepToString(findPairs(nums2, target2).toArray()));
    }
}

解释

方法:

该题解采用了哈希表的方法来解决问题。首先,遍历数组中的每个元素,对于当前元素n,检查target-n是否已经在哈希表中,如果存在,说明找到了一对和为target的数对,将这对数对添加到结果列表中,并将哈希表中对应的计数减一。如果不存在,将当前元素n添加到哈希表中,计数加一。这样可以确保每个数只能属于一个数对。

时间复杂度:

O(n)

空间复杂度:

O(n)

代码细节讲解

🦆
哈希表中如果已有元素n时,你是如何处理重复元素的情况,尤其是当数组中存在多个相同的n时?
在哈希表中,元素n的处理是通过记录每个元素的出现次数来管理的。如果数组中存在多个相同的n,则每次遍历到n时,都会在哈希表中增加n的计数(使用d[n] = d.get(n, 0) + 1)。这样,哈希表中的值(d[n])就代表元素n在数组中剩余的可用次数。当需要配对时,检查target-n是否存在,并且其计数大于0,如果是,则可以形成一对,并相应地减少其在哈希表中的计数。
🦆
在哈希表的更新过程中,当找到一对有效的数对后,减少哈希表中的计数可能会有什么潜在的问题?
减少哈希表中的计数是必要的步骤,以确保每个数字只被使用一次。然而,这种方法可能导致潜在的问题,如在并发环境下,如果哈希表的更新(减少计数)没有正确同步,可能会出现竞态条件,导致计数不准确。此外,如果代码中减少计数的逻辑不正确(例如,未检查计数是否大于0就减少),可能会导致计数变为负数,从而引发错误或不一致的行为。
🦆
给定题解中的哈希表处理方式,如何确保在遍历时每个数只能被用一次?
题解中通过在哈希表中记录每个元素的计数来确保每个数只能被用一次。对于每个遍历到的元素n,首先检查target-n是否已存在于哈希表中,并且其计数大于0。如果条件满足,说明可以形成一对,将该对添加到结果中,并将target-n的计数减一。这样就确保了一旦一个数字被用作配对,其在哈希表中的可用次数就会相应减少。如果target-n不在哈希表中或计数为0,则将n的计数增加,等待未来的配对。这种方法确保了每个数字最多只被使用一次来形成数对。

相关问题