
题目描述
给你一个整数数组 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 0 <= nums[i] <= 105
解法
方法一:枚举中间数字 + 哈希表
我们可以枚举中间数字 \(\textit{nums}[j]\),用两个哈希表 \(\textit{left}\) 和 \(\textit{right}\) 分别记录 \(\textit{nums}[j]\) 左侧和右侧的数字出现次数。
我们首先将所有数字加入 \(\textit{right}\) 中,然后从左到右遍历每个数字 \(\textit{nums}[j]\),在遍历过程中:
- 将 \(\textit{nums}[j]\) 从 \(\textit{right}\) 中移除。
- 计算 \(\textit{nums}[j]\) 左侧的数字 \(\textit{nums}[i] = \textit{nums}[j] * 2\) 的出现次数,记为 \(\textit{left}[\textit{nums}[j] * 2]\)。
- 计算 \(\textit{nums}[j]\) 右侧的数字 \(\textit{nums}[k] = \textit{nums}[j] * 2\) 的出现次数,记为 \(\textit{right}[\textit{nums}[j] * 2]\)。
- 将 \(\textit{left}[\textit{nums}[j] * 2]\) 和 \(\textit{right}[\textit{nums}[j] * 2]\) 相乘,得到以 \(\textit{nums}[j]\) 为中间数字的特殊三元组数量,并将结果累加到答案中。
- 将 \(\textit{nums}[j]\) 加入 \(\textit{left}\) 中。
最后返回答案。
时间复杂度为 \(O(n)\),空间复杂度为 \(O(n)\),其中 \(n\) 是数组 \(\textit{nums}\) 的长度。
| class Solution:
def specialTriplets(self, nums: List[int]) -> int:
left = Counter()
right = Counter(nums)
ans = 0
mod = 10**9 + 7
for x in nums:
right[x] -= 1
ans = (ans + left[x * 2] * right[x * 2] % mod) % mod
left[x] += 1
return ans
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 | class Solution {
public int specialTriplets(int[] nums) {
Map<Integer, Integer> left = new HashMap<>();
Map<Integer, Integer> right = new HashMap<>();
for (int x : nums) {
right.merge(x, 1, Integer::sum);
}
long ans = 0;
final int mod = (int) 1e9 + 7;
for (int x : nums) {
right.merge(x, -1, Integer::sum);
ans = (ans + 1L * left.getOrDefault(x * 2, 0) * right.getOrDefault(x * 2, 0) % mod)
% mod;
left.merge(x, 1, Integer::sum);
}
return (int) ans;
}
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 | class Solution {
public:
int specialTriplets(vector<int>& nums) {
unordered_map<int, int> left, right;
for (int x : nums) {
right[x]++;
}
long long ans = 0;
const int mod = 1e9 + 7;
for (int x : nums) {
right[x]--;
ans = (ans + 1LL * left[x * 2] * right[x * 2] % mod) % mod;
left[x]++;
}
return (int) ans;
}
};
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 | func specialTriplets(nums []int) int {
left := make(map[int]int)
right := make(map[int]int)
for _, x := range nums {
right[x]++
}
ans := int64(0)
mod := int64(1e9 + 7)
for _, x := range nums {
right[x]--
ans = (ans + int64(left[x*2])*int64(right[x*2])%mod) % mod
left[x]++
}
return int(ans)
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 | function specialTriplets(nums: number[]): number {
const left = new Map<number, number>();
const right = new Map<number, number>();
for (const x of nums) {
right.set(x, (right.get(x) || 0) + 1);
}
let ans = 0;
const mod = 1e9 + 7;
for (const x of nums) {
right.set(x, (right.get(x) || 0) - 1);
const lx = left.get(x * 2) || 0;
const rx = right.get(x * 2) || 0;
ans = (ans + ((lx * rx) % mod)) % mod;
left.set(x, (left.get(x) || 0) + 1);
}
return ans;
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32 | use std::collections::HashMap;
impl Solution {
pub fn special_triplets(nums: Vec<i32>) -> i32 {
let mut left: HashMap<i32, i64> = HashMap::new();
let mut right: HashMap<i32, i64> = HashMap::new();
for &x in &nums {
*right.entry(x).or_insert(0) += 1;
}
let modulo: i64 = 1_000_000_007;
let mut ans: i64 = 0;
for &x in &nums {
if let Some(v) = right.get_mut(&x) {
*v -= 1;
}
let t = x * 2;
let l = *left.get(&t).unwrap_or(&0);
let r = *right.get(&t).unwrap_or(&0);
ans = (ans + (l * r) % modulo) % modulo;
*left.entry(x).or_insert(0) += 1;
}
ans as i32
}
}
|