代码思路
-
排序:
- 首先对数组进行排序,这样可以简化后续的查找过程。排序后,相同的元素会聚集在一起,便于使用双指针技术。
-
双指针技术:
- 使用双指针技术来寻找满足条件的三元组。固定第一个元素
arr[i],然后使用两个指针left和right分别指向i+1和数组的末尾。 - 计算当前三个元素的和
current_sum = arr[i] + arr[left] + arr[right]。 - 如果
current_sum等于目标值t,则找到一个满足条件的三元组。 - 如果
current_sum小于目标值t,则移动左指针left向右,以增加和的值。 - 如果
current_sum大于目标值t,则移动右指针right向左,以减少和的值。
- 使用双指针技术来寻找满足条件的三元组。固定第一个元素
-
计数:
- 当找到一个满足条件的三元组时,计算其数量。如果
left和right指向的元素相同,则计算所有可能的组合数。否则,分别计算left和right指向的元素的重复次数,并计算组合数。
- 当找到一个满足条件的三元组时,计算其数量。如果
前置知识点
-
排序算法:
- 代码中使用了
std::sort函数对数组进行排序。std::sort是 C++ 标准库中的一个排序函数,它使用的是快速排序、堆排序和插入排序的混合算法,平均时间复杂度为O(n log n)。
- 代码中使用了
-
双指针技术:
- 双指针技术是一种常用的算法技巧,通常用于在有序数组中寻找满足某些条件的元素对或三元组。通过调整两个指针的位置,可以有效地减少不必要的遍历,从而提高算法的效率。
-
组合数学:
- 在计算满足条件的三元组数量时,需要用到组合数学的知识。例如,当
left和right指向的元素相同时,计算所有可能的组合数时,使用组合公式C(n, 2) = n * (n - 1) / 2。
- 在计算满足条件的三元组数量时,需要用到组合数学的知识。例如,当
-
取模运算:
- 题目要求结果对
10^9 + 7取模。取模运算可以防止整数溢出,并且在计算组合数时,可以避免中间结果过大。
- 题目要求结果对
关键步骤
- 排序:使用
std::sort对数组进行排序。 - 双指针:在固定第一个元素后,使用双指针
left和right来寻找满足条件的另外两个元素。 - 计数:当找到一个满足条件的三元组时,计算其数量。
完整代码
int solution(std::vector<int> &arr, int t) {
const int MOD = 1000000007;
int count = 0;
int n = arr.size();
std::sort(arr.begin(), arr.end());
for (int i = 0; i < n - 2; ++i) {
int left = i + 1;
int right = n - 1;
while (left < right) {
int current_sum = arr[i] + arr[left] + arr[right];
if (current_sum == t) {
if (arr[left] == arr[right]) {
count += (right - left + 1) * (right - left) / 2;
break;
} else {
int left_count = 1;
int right_count = 1;
while (left + 1 < right && arr[left] == arr[left + 1]) {
left_count++;
left++;
}
while (left < right - 1 && arr[right] == arr[right - 1]) {
right_count++;
right--;
}
count += left_count * right_count;
left++;
right--;
}
} else if (current_sum < t) {
left++;
} else {
right--;
}
}
}
return count % MOD;
}