2001. Number of Pairs of Interchangeable Rectangles - Explanation
Description
Each entry [width, height] in rectangles describes one rectangle. Count index pairs i < j whose width-to-height ratios are exactly equal. Dimensions may differ as long as the ratios match. Width and height keep their roles, so rotating a rectangle is not allowed; identical entries at different indices still form separate pairs. Return the total number of matching pairs.
Example 1:
Input: rectangles = [[2,3],[4,6],[6,9]]
Output: 3Explanation: All three rectangles have ratio 2/3. The index pairs (0,1), (0,2), and (1,2) match, giving 3.
Example 2:
Input: rectangles = [[2,3],[3,2]]
Output: 0Explanation: The ratios 2/3 and 3/2 differ. Rotation is not allowed, so there are no matching pairs.
Example 3:
Input: rectangles = [[5,5],[5,5],[2,2],[2,3]]
Output: 3Explanation: The first three entries are squares and each pair among them matches, giving 3 pairs. The last rectangle has a different ratio.
Constraints:
1 <= rectangles.length <= 100000- Each rectangle has exactly two entries:
[width, height]. 1 <= width, height <= 100000
Topics
Prerequisites
Before attempting this problem, you should be comfortable with:
- Hash Maps - Using dictionaries to count and group items by a computed key
- Ratio/Proportion Comparison - Understanding when two fractions (width/height) are equivalent
- Combinatorics (Counting Pairs) - Using the formula n*(n-1)/2 to count pairs from n items
- Greatest Common Divisor (GCD) - Reducing fractions to their simplest form to avoid floating-point precision issues
1. Brute Force
Intuition
Two rectangles are interchangeable if they have the same aspect ratio (width divided by height). The simplest approach is to compare every pair of rectangles and check if their ratios match. For each pair where the ratios are equal, we count it as an interchangeable pair.
Algorithm
- Initialize a counter
resto0. - For each rectangle
ifrom1ton-1:- For each rectangle
jfrom0toi-1:- If
rectangles[i][0] / rectangles[i][1]equalsrectangles[j][0] / rectangles[j][1], incrementres.
- If
- For each rectangle
- Return
res.
Time & Space Complexity
- Time complexity:
- Space complexity:
2. Hash Map (Two Pass)
Intuition
Instead of comparing every pair, we can group rectangles by their aspect ratio. Rectangles with the same ratio form a group, and any two rectangles in the same group are interchangeable. If a group has c rectangles, the number of pairs is c * (c-1) / 2 (choosing 2 from c). We use a hash map to count how many rectangles share each ratio.
Algorithm
- Create a hash map
countto store the frequency of each aspect ratio. - First pass: for each rectangle, compute its ratio and increment the count in the map.
- Second pass: for each ratio with count
c > 1, addc * (c-1) / 2to the result. - Return the total count of interchangeable pairs.
Time & Space Complexity
- Time complexity:
- Space complexity:
3. Hash Map (One Pass)
Intuition
We can optimize the two-pass approach into a single pass. As we process each rectangle, we check how many rectangles with the same ratio we have seen before. Each previously seen rectangle with the same ratio forms a new interchangeable pair with the current rectangle. This way, we count pairs incrementally as we go.
Algorithm
- Create a hash map
countto store the frequency of each aspect ratio. - Initialize
resto0. - For each rectangle:
- Compute its aspect ratio.
- Add the current count for this ratio to
res(each previous rectangle with this ratio forms a pair). - Increment the count for this ratio in the map.
- Return
res.
Time & Space Complexity
- Time complexity:
- Space complexity:
4. Greatest Common Divisor
Intuition
Using floating-point division for ratios can lead to precision issues with very large numbers. A more robust approach is to reduce each ratio to its simplest form using the greatest common divisor (GCD). Two rectangles have the same ratio if and only if their reduced forms are identical. We can pack the reduced width and height into a single integer key for efficient hashing.
Algorithm
- Create a hash map
countto store the frequency of each normalized ratio. - Initialize
resto0. - For each rectangle:
- Compute the
GCDof width and height. - Divide both by the
GCDto get the reduced form. - Create a unique hash key by combining the reduced width and height (e.g., using bit shifting).
- Add the current count for this key to
res. - Increment the count for this key in the map.
- Compute the
- Return
res.
class Solution:
def hash(self, a: int, b: int) -> int:
mask = a
mask |= (b << 31)
return mask
def interchangeableRectangles(self, rectangles: List[List[int]]) -> int:
res = 0
count = {}
for rect in rectangles:
gcd = math.gcd(rect[0], rect[1])
key = self.hash(rect[0] // gcd, rect[1] // gcd)
res += count.get(key, 0)
count[key] = count.get(key, 0) + 1
return resTime & Space Complexity
- Time complexity:
- Space complexity:
Common Pitfalls
Floating-Point Precision Errors
Using floating-point division to compute aspect ratios can lead to precision issues with large width/height values. Two ratios that should be equal may compare as unequal due to floating-point representation errors. The GCD-based approach avoids this by reducing ratios to their simplest integer form before comparison.
Integer Overflow in Pair Counting
When counting pairs using the formula c * (c - 1) / 2, the multiplication can overflow if c is large and you are using 32-bit integers. Ensure you use a 64-bit integer type (like long in Java or long long in C++) for the result and intermediate calculations.
Incorrect Pair Counting Formula
A common mistake is counting each pair twice by iterating over all i != j combinations, or forgetting to use the combination formula entirely. Remember that choosing 2 items from c items is c * (c - 1) / 2, not c * c or c * (c - 1).
Sign in to join the discussion