Number of Ways Where Square of Number Is Equal to Product of Two Numbers
LeetCode Number of Ways Where Square of Number Is Equal to Product of Two Numbers (Problem 1577) asks you to count triplets across two arrays where the square of one element equals the product of two elements from the other array.
The problem
Given two arrays of integers nums1 and nums2, return the number of triplets formed from two types:
- Type 1: Triplet
(i, j, k)wherenums1[i]^2 == nums2[j] * nums2[k]and0 <= i,0 <= j < k < nums2.length. - Type 2: Triplet
(i, j, k)wherenums2[i]^2 == nums1[j] * nums1[k]and0 <= i,0 <= j < k < nums1.length.
Example: nums1 = [7, 4], nums2 = [5, 2, 8, 9]. For Type 1, 4^2 = 16 = 2 * 8, so there is 1 triplet. No Type 2 triplets exist. The answer is 1.
The brute force approach
The most direct approach checks every possible triplet combination. For Type 1, iterate over every i in nums1, then every pair (j, k) in nums2 where j < k. Check if the square equals the product.
def numTriplets(nums1, nums2):
count = 0
for i in range(len(nums1)):
for j in range(len(nums2)):
for k in range(j + 1, len(nums2)):
if nums1[i] * nums1[i] == nums2[j] * nums2[k]:
count += 1
for i in range(len(nums2)):
for j in range(len(nums1)):
for k in range(j + 1, len(nums1)):
if nums2[i] * nums2[i] == nums1[j] * nums1[k]:
count += 1
return count
This runs in O(n * m^2 + m * n^2) time, which is too slow for large inputs. The triple nested loop is doing redundant work. We can precompute the product pairs.
The key insight
Instead of checking every pair on the fly, precompute a hash map of all product frequencies for one array. Then for each element in the other array, look up its square in the map. The count at that key tells you how many valid pairs exist.
For Type 1, build a map of all nums2[j] * nums2[k] products (where j < k) and their frequencies. Then for each nums1[i], check map[nums1[i]^2]. Do the same with roles reversed for Type 2.
The helper function handles one direction at a time. Call it twice with swapped arguments to cover both triplet types. This keeps the code clean and avoids duplication.
Step-by-step walkthrough
Let's trace through nums1 = [7, 4] and nums2 = [5, 2, 8, 9].
Step 1: Identify the two triplet types
Type 1 squares an element from nums1 and finds a product pair in nums2. Type 2 reverses the roles.
Step 2: Build a product frequency map for nums2
For nums2 = [5, 2, 8, 9], compute all products nums2[j] * nums2[k] where j < k. Store counts in a hash map.
Step 3: Check Type 1 triplets (square nums1 elements)
For each nums1[i], compute nums1[i]^2 and look it up in the product map. 7^2 = 49 is not in the map (0 matches). 4^2 = 16 is in the map with count 1. Type 1 total: 1.
Step 4: Build a product frequency map for nums1
For nums1 = [7, 4], the only pair is (0, 1): 7 * 4 = 28. Map: {28: 1}.
Step 5: Check Type 2 triplets (square nums2 elements)
5^2=25, 2^2=4, 8^2=64, 9^2=81. None of these appear in the nums1 product map {28:1}. Type 2 total: 0.
Step 6: Combine both types
Total = Type 1 + Type 2 = 1 + 0 = 1.
The final answer is 1. One Type 1 triplet (from 4^2 = 2 * 8) and zero Type 2 triplets.
The code
from collections import Counter
def numTriplets(nums1, nums2):
def count_triplets(squares, products):
prod_map = Counter()
n = len(products)
for j in range(n):
for k in range(j + 1, n):
prod_map[products[j] * products[k]] += 1
total = 0
for val in squares:
total += prod_map[val * val]
return total
return count_triplets(nums1, nums2) + count_triplets(nums2, nums1)
Here is what each piece does:
count_triplets(squares, products)handles one direction. It takes the array whose elements get squared and the array whose pairs form products.- Build
prod_mapby iterating over all pairs(j, k)wherej < kin the products array. Each product gets its frequency counted. - For each value in
squares, computeval * valand look up how many pairs produce that product. Add that count to the total. - Call the helper twice with swapped arguments to cover both Type 1 and Type 2 triplets.
Using Counter from Python's collections module means looking up a missing key returns 0 instead of raising a KeyError. This eliminates the need for explicit if key in map checks.
Complexity analysis
| Approach | Time | Space |
|---|---|---|
| Brute force | O(n * m^2 + m * n^2) | O(1) |
| Hash map | O(n^2 + m^2 + n + m) | O(n^2 + m^2) for product maps |
The hash map approach builds product maps in O(n^2) and O(m^2), then does linear lookups. The total is O(n^2 + m^2), which is much better than the cubic brute force for large inputs.
The building blocks
This problem is built on two reusable patterns that CodeBricks drills independently.
1. Product pair frequency counting
The pattern of precomputing all pairwise products in an array and storing their frequencies in a hash map:
prod_map = Counter()
for j in range(n):
for k in range(j + 1, n):
prod_map[arr[j] * arr[k]] += 1
This same approach works in any problem where you need to quickly look up how many pairs produce a given value. Two Sum uses addition instead of multiplication, but the structure is identical: precompute pair results and store them for O(1) lookup.
2. Symmetric role reversal
The pattern of solving a problem in one direction, then swapping roles and solving it again:
result = solve(nums1, nums2) + solve(nums2, nums1)
This appears in problems like 4Sum II, where you split the four arrays into two groups and count complementary sums. Recognizing that both directions use the same logic lets you write one helper function and call it twice.
Edge cases
Before submitting, make sure your solution handles these:
- All identical elements:
nums1 = [2, 2, 2],nums2 = [2, 2, 2]. Every element squares to 4, and every pair product is 4. The count grows quadratically with duplicates. - No valid triplets:
nums1 = [1],nums2 = [1]. Only one element in each array means no valid pairj < kcan be formed from either array. The answer is 0. - Large values: Elements can be up to 10^5, so squares can reach 10^10. Use 64-bit integers if your language requires it. Python handles big integers natively.
- Single element arrays: If one array has only one element, no pairs can form from it. Triplets can only come from the direction where the single-element array provides the square.
- Zeros in the arrays: If
nums1[i] = 0, then0^2 = 0, so you need pairs innums2whose product is 0. Any pair containing a zero element innums2qualifies.
From understanding to recall
You have seen the hash map approach and it makes sense. Precompute product frequencies, then look up each square. Two calls to the same helper cover both triplet types. Clean and efficient.
But in an interview, the pressure makes it easy to forget the symmetric structure, mix up which array gets squared versus paired, or fumble the pair enumeration. These are not understanding problems. They are recall problems.
Spaced repetition fixes this. You practice writing the product frequency map and the symmetric helper call from scratch at increasing intervals. After a few rounds, the pattern is automatic. You see "count triplets matching a target across two arrays" and the structure flows out: build map, look up squares, swap and repeat.
The product pair counting pattern is one of roughly 60 reusable building blocks that cover hundreds of LeetCode problems. Learning them individually and drilling them with spaced repetition is far more effective than grinding random problems and hoping they stick.
Related posts
- Two Sum - The classic complement lookup pattern that this problem extends from addition to multiplication
- 3Sum - Another problem that counts triplets matching a target, using sorting and two pointers instead of hash maps
- Subarray Sum Equals K - Prefix sums paired with hash map frequency counting, the same "precompute and look up" strategy
CodeBricks breaks the number of ways where square equals product LeetCode problem into its product pair counting and symmetric role reversal building blocks, then drills them independently with spaced repetition. You type each piece from scratch until the pattern is automatic. When a pair-counting question shows up in your interview, you do not think about it. You just write it.