给你一个整数数组 nums。
特殊三元组 定义为满足以下条件的下标三元组 (i, j, k):
0 <= i < j < k < n,其中 n = nums.length
numsi == numsj * 2
numsk == numsj * 2
返回数组中 特殊三元组 的总数。
由于答案可能非常大,请返回结果对 109 + 7 取余数后的值。
示例 1:
输入: nums = 6,3,6
输出: 1
解释:
唯一的特殊三元组是 (i, j, k) = (0, 1, 2),其中:
nums0 = 6, nums1 = 3, nums2 = 6
nums0 = nums1 * 2 = 3 * 2 = 6
nums2 = nums1 * 2 = 3 * 2 = 6
示例 2:
输入: nums = 0,1,0,0
输出: 1
解释:
唯一的特殊三元组是 (i, j, k) = (0, 2, 3),其中:
nums0 = 0, nums2 = 0, nums3 = 0
nums0 = nums2 * 2 = 0 * 2 = 0
nums3 = nums2 * 2 = 0 * 2 = 0
示例 3:
输入: nums = 8,4,2,8,4
输出: 2
解释:
共有两个特殊三元组:
(i, j, k) = (0, 1, 3)
nums0 = 8, nums1 = 4, nums3 = 8
nums0 = nums1 * 2 = 4 * 2 = 8
nums3 = nums1 * 2 = 4 * 2 = 8
(i, j, k) = (1, 2, 4)
nums1 = 4, nums2 = 2, nums4 = 4
nums1 = nums2 * 2 = 2 * 2 = 4
nums4 = nums2 * 2 = 2 * 2 = 4
提示:
3 <= n == nums.length <= 105^55
0 <= numsi <= 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)。