|
| 1 | +# [Problem 3583: Count Special Triplets](https://leetcode.com/problems/count-special-triplets/description/?envType=daily-question) |
| 2 | + |
| 3 | +## Initial thoughts (stream-of-consciousness) |
| 4 | +We need triplets (i, j, k) with i < j < k and nums[i] == nums[j]*2 and nums[k] == nums[j]*2. That means for any chosen center j, we are looking for equal values "need = 2 * nums[j]" both to the left and to the right of j. A brute-force triple loop is O(n^3) and impossible for n up to 1e5. For each j we just need the count of "need" on the left and the count on the right; multiply them to get the number of triplets using that j. So maintain counts of values to the left and right while scanning j from left to right. This suggests an O(n) single-pass approach using frequency maps. |
| 5 | + |
| 6 | +## Refining the problem, round 2 thoughts |
| 7 | +Implementation detail: initialize right-count as frequency of all numbers; left-count empty. For each index j in order: |
| 8 | +- decrement right-count for nums[j] (since j is not part of right-side anymore), |
| 9 | +- compute need = nums[j] * 2, |
| 10 | +- contribution = left_count[need] * right_count[need], |
| 11 | +- add contribution to answer, |
| 12 | +- increment left-count[nums[j]]. |
| 13 | + |
| 14 | +Edge cases: nums[j] can be 0 (then need=0) — the formula still works. need might exceed the original value range (up to 2*10^5), so use a dict/Counter (or array with size >= 2*max(nums)+1) to be safe. Use modulo 1e9+7 for the running total. Complexity: O(n) time, O(M) space where M is number of distinct values (or up to max value range). |
| 15 | + |
| 16 | +## Attempted solution(s) |
| 17 | +```python |
| 18 | +from collections import Counter |
| 19 | + |
| 20 | +class Solution: |
| 21 | + def countTriplets(self, nums: list[int]) -> int: |
| 22 | + MOD = 10**9 + 7 |
| 23 | + right = Counter(nums) # counts of values to the right (initially whole array) |
| 24 | + left = Counter() # counts of values to the left (initially empty) |
| 25 | + ans = 0 |
| 26 | + |
| 27 | + for val in nums: |
| 28 | + # this index j is being considered as the middle element |
| 29 | + # remove it from right (so right now represents indices > j) |
| 30 | + right[val] -= 1 |
| 31 | + if right[val] == 0: |
| 32 | + # optional cleanup to keep Counter small |
| 33 | + del right[val] |
| 34 | + |
| 35 | + need = val * 2 |
| 36 | + # number of choices for i is left[need], for k is right[need] |
| 37 | + ans = (ans + left.get(need, 0) * right.get(need, 0)) % MOD |
| 38 | + |
| 39 | + # include current val in left for future js |
| 40 | + left[val] += 1 |
| 41 | + |
| 42 | + return ans |
| 43 | +``` |
| 44 | +- Notes: |
| 45 | + - Approach: single pass over the array using two frequency counters (left and right). For each center j, multiply the counts of 2*nums[j] on the left and right to get the number of valid (i,k) pairs for that j. |
| 46 | + - Time complexity: O(n), where n = len(nums). Each element processed once and dictionary operations are average O(1). |
| 47 | + - Space complexity: O(M) for the counters, where M is the number of distinct values (or up to the value range, at most about 2 * max(nums) + 1 if using arrays). |
| 48 | + - Handles zeros and large values safely by using Counters; intermediate results are taken modulo 1e9+7. |
0 commit comments