三数之和问题 | 豆包MarsCode AI 刷题

152 阅读3分钟

问题描述

小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 时,有多个元组满足条件,你需要返回这些元组的数量。

测试样例

样例1:

输入: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

思路分析

  1. 初始化和预处理: 首先对数组 arr 进行升序排序,这将便于后续查找满足条件的元素组合。
  2. 双指针法: 使用两个指针 i, left 分别表示当前正在考虑的前两个元素的位置,而 right 初始指向数组末尾。这样使得我们可以从每个位置开始,尝试寻找一个合适的中间值 arr[right] 来达到目标和。
  3. 循环检查和更新: 当三者之和小于目标值时,增加左指针 left;当三者之和大于目标值时,减少右指针 right。如果和正好等于目标值,说明找到了符合条件的一组。
  4. 处理重复元素: 对于相同的元素 arr[left]arr[right],有两种情况:如果它们都相同,则计算从 left+1right-1 这段区间的组合数;如果只有一部分相同,我们分别计数相等元素的数量,然后乘以另一端的组合数。
  5. 累加计数: 根据找到的不同组合方式,将对应的组合数累加到变量 count 中,并在每次结束后对其取模 mod
  6. 返回结果: 循环结束后,返回计算得到的组合数对 10^9 + 7 取模的结果作为最终答案

代码详解

涉及到的知识点

1. 排序算法:通过 arr.sort() 实现了数组的升序排列,方便了接下来的线性搜索。

2. 双指针法:使用 i, left, 和 right 三个指针,利用动态范围缩小的方式,提高了查找满足条件的元素组合的效率。

3. 二分查找思想:虽然没有明确的二分查找,但在不断调整左右边界的过程中,类似于二分查找的区间判断(如和小于目标则向左找,大于向右找)。

4. 组合数学:在处理重复元素的情况下,计算组合数,特别是当元素相同时,利用组合公式 (n choose k) 的简化形式 k*(n-k)

5. 取模运算:对最后的组合数取模 10^9 + 7,是为了防止结果溢出,因为题目要求结果对这个数取模。

6. 数组操作和迭代:遍历数组并处理不同情况下的指针移动,体现了对数组操作的理解。

7. 动态规划优化:尽管这里没有明显的动态规划结构,但在处理重复元素时避免了不必要的重复计算,间接地体现了动态规划的思想。