The "Tuple with Same Product" problem asks you to count the number of unique tuples (a, b, c, d)
such that:
a
, b
, c
, and d
are distinct integers from a given array nums
.a * b == c * d
.a
, b
, c
, and d
are all different indices (no element is reused).4 <= nums.length <= 1000
1 <= nums[i] <= 10^4
At first glance, you might consider checking every combination of four distinct numbers to see if the product of one pair equals the product of the other. However, with up to 1000 elements, this brute-force approach would be computationally expensive (since there are O(n4) quadruples).
Instead, let's reframe the problem: For two pairs (a, b)
and (c, d)
with distinct elements, if a * b == c * d
, then the pairs are interchangeable for our tuple. So, if we can count how many unique pairs result in the same product, we can count the number of ways to pick two such pairs to form a tuple.
This leads to the idea of grouping all pairs by their product, then counting how many ways two different pairs can be chosen from each group.
Let's break down the optimized approach step by step:
(i, j)
in nums
(with i < j
), compute the product nums[i] * nums[j]
.C(n, 2) = n*(n-1)/2
where n
is the number of pairs with that product.(a, b)
and (c, d)
, the elements can be arranged as (a, b, c, d)
, (a, b, d, c)
, (b, a, c, d)
, (b, a, d, c)
, (c, d, a, b)
, (c, d, b, a)
, (d, c, a, b)
, (d, c, b, a)
(since order of each pair matters). So, we multiply by 8.
Sample Input: nums = [2, 3, 4, 6]
Step 1: Generate all pairs and their products:
a*b == c*d
with all elements distinct is with (2,6,3,4) and permutations thereof.
Brute-force approach:
The key insight is to reduce the quadruple search space by grouping all pairs by their product using a hash map. By counting how many pairs share the same product, we can efficiently calculate the number of valid tuples without redundant computation. This approach leverages combinatorics and hash maps for an elegant and scalable solution.
from collections import defaultdict
class Solution:
def tupleSameProduct(self, nums):
product_count = defaultdict(int)
n = len(nums)
for i in range(n):
for j in range(i+1, n):
prod = nums[i] * nums[j]
product_count[prod] += 1
result = 0
for count in product_count.values():
if count > 1:
result += count * (count - 1) // 2 * 8
return result
#include <unordered_map>
#include <vector>
using namespace std;
class Solution {
public:
int tupleSameProduct(vector<int>& nums) {
unordered_map<int, int> product_count;
int n = nums.size();
for (int i = 0; i < n; ++i) {
for (int j = i + 1; j < n; ++j) {
int prod = nums[i] * nums[j];
product_count[prod]++;
}
}
int result = 0;
for (auto& [prod, count] : product_count) {
if (count > 1) {
result += count * (count - 1) / 2 * 8;
}
}
return result;
}
};
import java.util.*;
class Solution {
public int tupleSameProduct(int[] nums) {
Map<Integer, Integer> productCount = new HashMap<>();
int n = nums.length;
for (int i = 0; i < n; i++) {
for (int j = i + 1; j < n; j++) {
int prod = nums[i] * nums[j];
productCount.put(prod, productCount.getOrDefault(prod, 0) + 1);
}
}
int result = 0;
for (int count : productCount.values()) {
if (count > 1) {
result += count * (count - 1) / 2 * 8;
}
}
return result;
}
}
/**
* @param {number[]} nums
* @return {number}
*/
var tupleSameProduct = function(nums) {
const productCount = new Map();
const n = nums.length;
for (let i = 0; i < n; i++) {
for (let j = i + 1; j < n; j++) {
const prod = nums[i] * nums[j];
productCount.set(prod, (productCount.get(prod) || 0) + 1);
}
}
let result = 0;
for (const count of productCount.values()) {
if (count > 1) {
result += count * (count - 1) / 2 * 8;
}
}
return result;
};