1. 概述

本教程将展示如何在Java中实现一个算法:找出数组中所有和等于给定数字的数字对。我们将重点介绍两种不同的解题思路

第一种方法会找出所有可能的组合(允许重复),第二种方法则只返回唯一的数字组合,剔除冗余对。

针对每种思路,我们都会提供两种实现方式:

  1. 传统的 for 循环实现
  2. Java 8 Stream API 实现

2. 返回所有匹配对(含重复)

2.1 暴力解法

我们将使用暴力嵌套循环遍历整数数组,找出所有满足 i + j = sum 的数字对。**这种方法的时间复杂度为 O(n²)**。

以目标和 6 为例,使用以下输入数组:

int[] input = {2, 4, 3, 3, 5, 7, 1};

算法应返回所有可能的组合(含重复):

{2,4}, {4,2}, {3,3}, {3,3}

当找到满足条件的数字对时,通过工具方法 addPairs(i, j) 收集结果。

传统 for 循环实现

for (int i = 0; i < input.length; i++) {
    for (int j = 0; j < input.length; j++) {
        if (i != j && input[i] + input[j] == sum) {
            addPairs(input[i], input[j]);
        }
    }
}

Java 8 Stream API 实现

IntStream.range(0, input.length)
    .forEach(i -> IntStream.range(0, input.length)
        .filter(j -> i != j && input[i] + input[j] == sum)
        .forEach(j -> addPairs(input[i], input[j])));

⚠️ 踩坑提醒:这种方法会包含重复对(如 {2,4}{4,2}),且时间复杂度较高,仅适用于小规模数据。

3. 返回唯一匹配对(去重)

3.1 优化解法

本方法需要更高效的算法,仅返回唯一数字组合。核心思路:

  1. 使用 HashMap 存储已处理的数字
  2. 检查 sum - currentNum 是否已存在
  3. 避免重复记录(如 {2,4}{4,2} 视为同一组合)

使用相同的输入数组和目标和 6,预期输出:

{2,4}, {3,3}

传统 for 循环实现

Map<Integer, Integer> seen = new HashMap<>();
for (int num : input) {
    int complement = sum - num;
    if (seen.containsKey(complement)) {
        addPairs(complement, num);
        seen.remove(complement); // 避免重复使用
    } else {
        seen.put(num, complement);
    }
}

优化点:时间复杂度降至 **O(n)**,仅用单层循环。

Java 8 Stream API 实现

Map<Integer, Integer> pairs = new HashMap<>();
IntStream.range(0, input.length).forEach(i -> {
    int current = input[i];
    int complement = sum - current;
    
    if (pairs.containsKey(current)) {
        if (pairs.get(current) != null) {
            addPairs(current, complement);
        }
        pairs.put(current, null); // 标记已使用
    } else if (!pairs.containsValue(complement)) {
        pairs.put(complement, current);
    }
});

⚠️ 关键逻辑

  • 通过 containsValue 检查避免反向重复
  • null 标记已匹配的数字,防止二次利用

4. 总结

本文对比了在Java中解决两数之和问题的两种核心策略

  1. 暴力解法:简单直接但效率低(O(n²)),适合快速验证
  2. 优化解法:利用HashMap去重且高效(O(n)),适合生产环境

每种策略都提供了传统循环和Stream API两种实现。完整代码示例可在GitHub仓库获取(Maven工程,可直接编译运行)。

💡 开发建议:实际项目中优先选择优化解法,但需注意HashMap的内存开销。对于超大规模数据,可考虑排序后使用双指针法进一步优化。


原始标题:Find All Pairs of Numbers in an Array That Add Up to a Given Sum in Java