Leetcode 3625. Count Number of Trapezoids II
Count the number of 4-point subsets that form a trapezoid — i.e., a convex quadrilateral with at least one pair of parallel sides — from up to 500 distinct points. The core challenge is combinatorially counting pairs of disjoint point-segments with the same slope (parallel sides) while excluding degenerate/overlapping cases, typically done by grouping point-pairs by reduced slope in O(n^2) time.
DESCRIPTION
Count the number of 4-point subsets that form a trapezoid — i.e., a convex quadrilateral with at least one pair of parallel sides — from up to 500 distinct points.
The core challenge is combinatorially counting pairs of disjoint point-segments with the same slope (parallel sides) while excluding degenerate/overlapping cases, typically done by grouping point-pairs by reduced slope in O(n^2) time.
Input:
points = [[0,0], [1,0], [0,1], [1,1]]
Output:
1
Explanation: The 4 points form a square, which is a trapezoid (both pairs of opposite sides are parallel). This is the only 4-point subset, so count is 1.
Constraints:
- 4 <= points.length <= 500
- points[i].length == 2
- -10^9 <= points[i][0], points[i][1] <= 10^9
- All points are distinct (no duplicates)
- The answer will fit in a 32-bit integer
Understanding the Problem
Let's understand what we're being asked to do. We have up to 500 distinct points in a 2D plane, and we need to count how many 4-point subsets form a trapezoid - a convex quadrilateral with at least one pair of parallel sides.
For example, given points [[0,0], [1,0], [0,1], [1,1]] (forming a square), we can select all 4 points to form a trapezoid (actually a special trapezoid where both pairs of opposite sides are parallel).
Important constraint: The points must form a convex quadrilateral (no point inside the shape formed by the other three), and we need at least one pair of parallel sides. Two line segments are parallel if they have the same slope.
Key challenge: With 500 points, there are C(500,4) ≈ 2.6 billion possible 4-point subsets. We can't check each one individually! We need to group point-pairs by their slope and count valid combinations.
Edge cases to consider: What if three or more points are collinear (on the same line)? These don't form valid trapezoids. What if two point-pairs overlap (share a point)? We need disjoint pairs for valid trapezoids.
Brute Force Approach
The brute-force approach enumerates all possible 4-point subsets using four nested loops, checking each combination to see if it forms a valid trapezoid. For each subset, we compute slopes of all six possible line segments, check if at least one pair of opposite sides is parallel (same slope), and verify the quadrilateral is convex (no point inside the triangle formed by the other three). This approach is straightforward but extremely inefficient with O(n^4) time complexity, making it impractical for 500 points.
Start trapezoid counting with brute force
0 / 24
Test Your Knowledge
Login to take the complexity quiz and track your progress
Complexity Analysis
Time Complexity: O(n^4) Four nested loops to enumerate all C(n,4) combinations of 4 points, with constant work per combination to check trapezoid validity
Space Complexity: O(1) Only constant extra space needed for slope calculations and validity checks
Building Intuition
A trapezoid requires at least one pair of parallel sides. Two line segments are parallel if they connect points with the same slope.
If we group all point-pairs by their slope (in reduced form like dy/dx), then any two pairs from the same slope group are parallel! The key is finding pairs of disjoint point-pairs (no shared points) with the same slope.
Instead of checking all C(n,4) combinations of 4 points (which would be O(n^4)), we can:
- Compute slopes for all O(n^2) point-pairs
- Group pairs by slope
- For each slope group, count combinations of disjoint pairs
This transforms a brute-force O(n^4) problem into an O(n^2) grouping problem with efficient counting.
Think of organizing point-pairs into buckets by their slope:
- Bucket for slope 0 (horizontal): all horizontal segments
- Bucket for slope 1: all segments with 45° angle
- Bucket for slope ∞ (vertical): all vertical segments
- etc.
Within each bucket, if we pick any two segments that don't share a point, we have a pair of parallel sides! Now we just need to verify the 4 points form a convex quadrilateral (not degenerate/overlapping).
The challenge is efficiently counting valid combinations within each slope bucket while excluding overlapping pairs.
Common Mistakes
Optimal Solution
The optimal approach groups all point-pairs by their slope (reduced to lowest terms to handle precision). For each slope group, we count combinations of disjoint point-pairs (pairs that don't share any points). Two disjoint pairs with the same slope form parallel sides of a potential trapezoid. We iterate through all O(n^2) point-pairs once, hash them by slope, then for each slope group, count valid disjoint pair combinations while excluding degenerate cases (collinear points, overlapping segments). This reduces the problem from O(n^4) enumeration to O(n^2) grouping with efficient counting.
Initialize trapezoid counting with geometry visualization
0 / 84
Test Your Knowledge
Login to take the complexity quiz and track your progress
Complexity Analysis
Time Complexity: O(n^2) Computing slopes for all point-pairs takes O(n^2). For each slope group, counting disjoint pairs is proportional to the group size, which sums to O(n^2) across all groups.
Space Complexity: O(n^2) Storing all point-pairs grouped by slope requires O(n^2) space in the worst case where all pairs have different slopes
What We've Learned
- Slope-based grouping with GCD normalization: When counting geometric relationships involving parallel lines, group point-pairs by their reduced slope (dy/dx after dividing by GCD) as a hashmap key. This transforms an O(n⁴) brute-force trapezoid check into O(n²) by pre-computing all parallel segment pairs, enabling efficient counting of combinations.
- Combinatorial counting over enumeration: Instead of enumerating all 4-point subsets (O(n⁴)), count trapezoids by iterating through pairs of parallel segments and using C(k,2) = k*(k-1)/2 to count valid trapezoids formed by k parallel segments with the same slope. This reduces complexity dramatically when many point-pairs share the same slope.
- Disjoint segment validation: The critical implementation detail is ensuring the two parallel sides share no common points - use set operations or coordinate checks to verify that segments (p1,p2) and (p3,p4) have no overlap before counting them as a valid trapezoid, preventing degenerate cases where points coincide.
- Vertical slope edge case: Always handle vertical lines separately (dx=0) since division by zero breaks slope calculations. Store vertical segments with a special key like (infinity, x-coordinate) or use a separate data structure, as this is a common source of runtime errors in geometry problems.
- Hash key design for geometric properties: Use tuple keys of (normalized_dy, normalized_dx) rather than floating-point slope values to avoid precision errors. Integer-based keys with GCD reduction ensure exact equality checks and prevent hash collisions from floating-point rounding, crucial for correctness in computational geometry.
- Pattern applies to collinearity and parallelism problems: This slope-grouping technique extends to any problem requiring detection of parallel segments, collinear points, or angle-based relationships - think of it whenever you need to find geometric patterns across multiple point combinations (convex hulls, line intersections, polygon detection).
Related Concepts and Problems to Practice
medium
This problem counts valid geometric shapes (triangles) from a set of elements by checking geometric constraints, similar to counting trapezoids. Both require combinatorial enumeration and validation of geometric properties across multiple elements.
medium
Counting trapezoids involves systematically exploring combinations of 4 points and checking validity constraints. Combination Sum teaches the backtracking pattern for exploring combinatorial spaces efficiently, which is conceptually related to enumerating point subsets.
Test Your Understanding
Why is geometry the right data structure for this problem?
geometry provides the optimal access pattern
It's the only data structure that works
It's the easiest to implement
It uses the least memory
Select an answer to see the explanation
Question Timeline
See when this question was last asked and where, including any notes left by other candidates.
Comments
Hello Interview Premium
Your account is free and you can post anonymously if you choose.