Want Help Cracking FAANG?

(Then click this)

×
Back to Question Bank

1726. Tuple with Same Product - Leetcode Solution

Problem Description

The "Tuple with Same Product" problem asks you to count the number of unique tuples (a, b, c, d) such that:

  • All elements a, b, c, and d are distinct integers from a given array nums.
  • The product of the first pair equals the product of the second pair, i.e., a * b == c * d.
  • All elements are distinct: a, b, c, and d are all different indices (no element is reused).
  • The order of tuples matters. Each valid tuple is counted according to all possible permutations that fit the above constraints.

Constraints:
  • 4 <= nums.length <= 1000
  • 1 <= nums[i] <= 10^4

The task is to return the total number of such tuples.

Thought Process

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.

Solution Approach

Let's break down the optimized approach step by step:

  1. Generate All Unique Pairs:
    • For every unique pair (i, j) in nums (with i < j), compute the product nums[i] * nums[j].
  2. Group Pairs by Product:
    • Use a hash map (dictionary) to count how many pairs yield each product.
  3. Count Valid Tuples:
    • For each product that appears in at least two pairs, the number of ways to choose two pairs is C(n, 2) = n*(n-1)/2 where n is the number of pairs with that product.
    • Each such selection of two pairs corresponds to 8 valid tuples: because for each pair, (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.
  4. Sum All Valid Tuples:
    • Iterate through all products in the hash map, and sum the results for all products with at least two pairs.

Why a hash map? Because it allows us to group and count pairs with the same product efficiently in O(1) time per insertion.

Example Walkthrough

Sample Input: nums = [2, 3, 4, 6]

Step 1: Generate all pairs and their products:

  • (2,3): 6
  • (2,4): 8
  • (2,6): 12
  • (3,4): 12
  • (3,6): 18
  • (4,6): 24
Products and counts:
  • 6: 1 pair
  • 8: 1 pair
  • 12: 2 pairs ((2,6) and (3,4))
  • 18: 1 pair
  • 24: 1 pair
Step 2: For product 12, there are 2 pairs.
Number of ways to pick two pairs: C(2,2) = 1.
Each such pair gives 8 tuples: 1 * 8 = 8.
Final Answer: 8 valid tuples.

Why? The only way to make a*b == c*d with all elements distinct is with (2,6,3,4) and permutations thereof.

Time and Space Complexity

Brute-force approach:

  • There are O(n4) quadruples to check, which is infeasible for n up to 1000.
Optimized approach:
  • Generating all pairs: O(n2).
  • Grouping by product using a hash map: O(1) per insertion, total O(n2).
  • Iterating through products: O(n2) in the worst case (all pairs have unique products), but typically much less.
  • Total time complexity: O(n2)
  • Space complexity: O(n2) for the hash map in the worst case.
Why? Because we only consider all unique pairs, not quadruples, and hash map operations are efficient.

Summary

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.

Code Implementation

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;
};