给你一个整数数组 nums。
特殊三元组 定义为满足以下条件的下标三元组 (i, j, k):
0 <= i < j < k < n,其中 n = nums.length
nums[i] == nums[j] * 2
nums[k] == nums[j] * 2
返回数组中 特殊三元组 的总数。
由于答案可能非常大,请返回结果对 109 + 7 取余数后的值。
示例 1:
输入: nums = [6,3,6]
输出: 1
解释:
唯一的特殊三元组是 (i, j, k) = (0, 1, 2),其中:
nums[0] = 6, nums[1] = 3, nums[2] = 6
nums[0] = nums[1] * 2 = 3 * 2 = 6
nums[2] = nums[1] * 2 = 3 * 2 = 6
示例 2:
输入: nums = [0,1,0,0]
输出: 1
解释:
唯一的特殊三元组是 (i, j, k) = (0, 2, 3),其中:
nums[0] = 0, nums[2] = 0, nums[3] = 0
nums[0] = nums[2] * 2 = 0 * 2 = 0
nums[3] = nums[2] * 2 = 0 * 2 = 0
示例 3:
输入: nums = [8,4,2,8,4]
输出: 2
解释:
共有两个特殊三元组:
(i, j, k) = (0, 1, 3)
nums[0] = 8, nums[1] = 4, nums[3] = 8
nums[0] = nums[1] * 2 = 4 * 2 = 8
nums[3] = nums[1] * 2 = 4 * 2 = 8
(i, j, k) = (1, 2, 4)
nums[1] = 4, nums[2] = 2, nums[4] = 4
nums[1] = nums[2] * 2 = 2 * 2 = 4
nums[4] = nums[2] * 2 = 2 * 2 = 4
提示:
3 <= n == nums.length <= 105^55
0 <= nums[i] <= 105^55
法一:先记录整个数组中每个数字的出现次数作为后缀数组,然后遍历nums,枚举j,记录下来前面出现过的数字及其频数,找出所有特殊三元组即可:
cpp
class Solution {
public:
int specialTriplets(vector<int>& nums) {
int n = nums.size();
unordered_map<int, int> suf;
for (int num : nums) {
++suf[num];
}
unordered_map<int, int> pre;
long long ans = 0;
for (int num : nums) {
--suf[num];
ans += (long long)pre[num * 2] * suf[num * 2];
++pre[num];
}
return ans % (long long)(1e9 + 7);
}
};
此算法时间复杂度为O(n),空间复杂度为O(n)。
法二:一次遍历,枚举k:
cpp
class Solution {
public:
int specialTriplets(vector<int>& nums) {
int n = nums.size();
unordered_map<int, int> cnt1;
unordered_map<int, long long> cnt2;
long long ans = 0;
for (int num : nums) {
// 此时num当成k,看有多少个ij对符合条件
if (!(num & 1)) {
ans += cnt2[num / 2];
}
// 此时num当成j,看有多少个i符合条件
cnt2[num] += cnt1[num * 2];
// 此时num当成i
++cnt1[num];
}
return ans % (long long)(1e9 + 7);
}
};
此算法时间复杂度为O(n),空间复杂度为O(n)。