“三数之和问题”题目要求
一、问题描述
小U有一个整数数组 arr,他希望找到其中三个元素 i, j, k 满足条件 i < j < k 且 arr[i] + arr[j] + arr[k] == target。由于可能存在大量的元组,结果需要对 10^9 + 7 取模。
例如:当 arr = [1,1,2,2,3,3,4,4,5,5] 且 t = 8 时,有多个元组满足条件,你需要返回这些元组的数量。
二、测试样例
输入:
arr = [1,1,2,2,3,3,4,4,5,5], t = 8
输出:20
样例2:
输入:
arr = [2,2,2,2], t = 6
输出:4
样例3:
输入:
arr = [1,2,3,4,5], t = 9
输出:2
样例4:
输入:
arr =[1,1,1,1], t = 3
输出:4
三、题目解析
3.1代码思路
1.定义常量与变量
- 初始化模值:定义常量
MOD = 1000000007,用于后续结果取模。 - 初始化计数器:定义变量
count,记录满足条件的三数组合数量。
2.遍历所有可能的三元组
使用三重嵌套循环,分别枚举三个数组下标 i, j, 和 k,确保:
i < j < k,避免重复组合。
具体过程:
(1)外层循环 (i)** :从数组起始位置开始,枚举第一个数的下标 i。
(2) 从 i+1 开始,枚举第二个数的下标 j。
(3)从 j+1 开始,枚举第三个数的下标 k。
3.判断三数之和是否等于目标值
在内层循环中,检查三元组是否满足 arr[i] + arr[j] + arr[k] == t 的条件:
-
若条件成立,将计数器
count加 1。 -
每次累加后,对计数器取模,避免溢出:
count = (count + 1) % MOD;
4.返回结果
当所有三元组都遍历完毕后,返回计数器 count 的最终值,即满足条件的三元组数量。
3.2详细代码
public class Main {
public static int solution(int[] arr, int t) {
int MOD = 1000000007;
int count = 0;
// 使用三重循环来遍历数组,找到满足条件的 i, j, k 组合
for (int i = 0; i < arr.length; i++) {
for (int j = i + 1; j < arr.length; j++) {
for (int k = j + 1; k < arr.length; k++) {
// 检查是否满足条件 arr[i] + arr[j] + arr[k] == t
if (arr[i] + arr[j] + arr[k] == t) {
count = (count + 1) % MOD;
}
}
}
}
return count;
}
public static void main(String[] args) {
System.out.println(solution(new int[]{1, 1, 2, 2, 3, 3, 4, 4, 5, 5}, 8) == 20);
System.out.println(solution(new int[]{2, 2, 2, 2}, 6) == 4);
System.out.println(solution(new int[]{1, 2, 3, 4, 5}, 9) == 2);
System.out.println(solution(new int[]{1, 1, 1, 1}, 3) == 4);
}
}
四、知识总结
技术点 1:组合遍历的简单性与直接性
代码采用三重循环来枚举所有可能的三元组组合 (i, j, k),并通过判断 arr[i] + arr[j] + arr[k] == t 来确定是否满足条件。优点包括:
- 清晰直观:逻辑直接以数组下标为中心,明确指出了组合的生成方式。
- 固定次序:利用
i < j < k的约束,减少了无效排列,提高了效率。
技术点 2:大数取模的处理
由于可能的组合数量较大,结果对 109+710^9+7109+7 取模:
count = (count + 1) % MOD;
这一设计的优点是:
- 避免整数溢出:对于可能的高频组合,确保结果始终可控。
- 符合实际需求:取模操作常见于需要限制结果范围的问题场景,尤其在竞赛中被广泛使用。
代码设计的核心思想是穷举法结合约束条件的逐步缩减。这种方法利用以下思路:
- 穷举所有可能性
通过三重循环,枚举数组中所有三数组合。这种方式保证了不会遗漏任何可能的组合。 - 约束条件的逐步筛选
使用i < j < k约束以及arr[i] + arr[j] + arr[k] == t条件,逐步剔除无效组合,最终仅保留符合要求的结果。 - 结果优化与规约
通过取模操作,使代码在应对大规模输入时依然能够高效计算并返回正确结果。
五、性能分析
1. 时间复杂度
代码使用了三重嵌套循环,分别遍历数组的三个元素 i, j, k,每层循环的复杂度为 O(n)。
因此,总时间复杂度为:O(n3)
这意味着,当数组长度 n 较大时,运行时间会显著增加,适合小规模输入的情况。
2. 空间复杂度
代码只使用了常量级别的变量:
- 整数变量
count和MOD。
没有额外的数据结构或递归调用,空间复杂度为:O(1) 即,代码的空间开销非常小,适用于内存受限的场景。