Facebook Pixel

1037. Valid Boomerang

Problem Description

You are given an array points containing exactly three points on a 2D coordinate plane, where each point is represented as [x, y].

Your task is to determine if these three points form a boomerang.

A boomerang is defined as a set of three points that satisfy two conditions:

  1. All three points must be distinct (no two points are the same)
  2. The three points must not be in a straight line (they must not be collinear)

The solution checks whether the three points are collinear by comparing slopes. For three points (x1, y1), (x2, y2), and (x3, y3), if they lie on the same line, the slope from point 1 to point 2 would equal the slope from point 2 to point 3.

Instead of directly comparing slopes as (y2 - y1)/(x2 - x1) ≠ (y3 - y2)/(x3 - x2), the code uses cross-multiplication to avoid division by zero issues: (y2 - y1) * (x3 - x2) ≠ (y3 - y2) * (x2 - x1).

If this inequality holds true, the points form a boomerang shape (they are not collinear), and the function returns true. Otherwise, it returns false.

Quick Interview Experience
Help others by sharing your interview experience
Have you seen this problem before?

Intuition

To determine if three points form a boomerang, we need to verify they don't all lie on the same straight line. The key insight is that if three points are collinear (on the same line), they share the same slope between consecutive pairs.

Think of it this way: if you're walking from point A to point B, and then from point B to point C, and all three points are on the same line, you're maintaining the same direction throughout your journey. The "steepness" or slope of your path remains constant.

Mathematically, for points to be collinear, the slope from the first point to the second point must equal the slope from the second point to the third point. If these slopes are different, the points must form a triangle or "boomerang" shape.

The slope between two points (x1, y1) and (x2, y2) is calculated as (y2 - y1)/(x2 - x1). So we want to check if: (y2 - y1)/(x2 - x1) ≠ (y3 - y2)/(x3 - x2)

However, division can be problematic when x2 - x1 = 0 or x3 - x2 = 0 (vertical lines). To avoid division by zero and potential floating-point precision issues, we can cross-multiply the inequality:

(y2 - y1) * (x3 - x2) ≠ (y3 - y2) * (x2 - x1)

This transformation preserves the inequality relationship while eliminating the need for division. If this cross-product inequality is true, the slopes are different, meaning the points don't lie on the same line and therefore form a valid boomerang.

Learn more about Math patterns.

Solution Approach

The implementation uses a straightforward mathematical approach based on slope comparison through cross-multiplication.

Step-by-step implementation:

  1. Extract the three points: We unpack the input array to get three points with their coordinates:

    (x1, y1), (x2, y2), (x3, y3) = points
  2. Apply the cross-multiplication formula: Instead of comparing slopes directly, we use the transformed equation to avoid division:

    return (y2 - y1) * (x3 - x2) != (y3 - y2) * (x2 - x1)

Why this works:

  • If the three points are collinear, the slopes between consecutive pairs of points are equal: (y2 - y1)/(x2 - x1) = (y3 - y2)/(x3 - x2)
  • Cross-multiplying this equation gives us: (y2 - y1) * (x3 - x2) = (y3 - y2) * (x2 - x1)
  • To check if points form a boomerang (are NOT collinear), we check if this equality does NOT hold

Handling edge cases:

The cross-multiplication approach elegantly handles special cases:

  • Vertical lines: When x2 - x1 = 0 or x3 - x2 = 0, direct slope calculation would cause division by zero. The cross-multiplication avoids this issue entirely.
  • Duplicate points: If any two points are the same, the formula will correctly identify them as collinear (not a boomerang).

Time and Space Complexity:

  • Time Complexity: O(1) - We perform a constant number of arithmetic operations regardless of input
  • Space Complexity: O(1) - We only use a fixed amount of extra space for storing the extracted coordinates

Ready to land your dream job?

Unlock your dream job with a 5-minute evaluator for a personalized learning plan!

Start Evaluator

Example Walkthrough

Let's walk through the solution with a concrete example to see how it determines if three points form a boomerang.

Example 1: Points that form a boomerang

Input: points = [[1, 1], [2, 3], [3, 2]]

Step 1: Extract the coordinates

  • Point 1: (x1, y1) = (1, 1)
  • Point 2: (x2, y2) = (2, 3)
  • Point 3: (x3, y3) = (3, 2)

Step 2: Calculate the left side of the inequality

  • (y2 - y1) * (x3 - x2) = (3 - 1) * (3 - 2) = 2 * 1 = 2

Step 3: Calculate the right side of the inequality

  • (y3 - y2) * (x2 - x1) = (2 - 3) * (2 - 1) = (-1) * 1 = -1

Step 4: Compare the results

  • Is 2 ≠ -1? Yes!
  • Since the values are different, the points are NOT collinear
  • Therefore, they form a boomerang → Return true

Example 2: Points that are collinear (NOT a boomerang)

Input: points = [[1, 1], [2, 2], [3, 3]]

Step 1: Extract the coordinates

  • Point 1: (x1, y1) = (1, 1)
  • Point 2: (x2, y2) = (2, 2)
  • Point 3: (x3, y3) = (3, 3)

Step 2: Calculate the left side

  • (y2 - y1) * (x3 - x2) = (2 - 1) * (3 - 2) = 1 * 1 = 1

Step 3: Calculate the right side

  • (y3 - y2) * (x2 - x1) = (3 - 2) * (2 - 1) = 1 * 1 = 1

Step 4: Compare the results

  • Is 1 ≠ 1? No!
  • Since the values are equal, the points ARE collinear (they lie on the line y = x)
  • Therefore, they do NOT form a boomerang → Return false

The cross-multiplication technique elegantly avoids division while correctly identifying whether the three points have the same slope between them, determining if they form a valid boomerang shape.

Solution Implementation

1class Solution:
2    def isBoomerang(self, points: List[List[int]]) -> bool:
3        """
4        Determine if three points form a valid boomerang (non-collinear points).
5      
6        Three points form a boomerang if they are not all on the same straight line.
7        We check this by comparing the slopes between point pairs.
8      
9        Args:
10            points: List of three points, each point is [x, y]
11      
12        Returns:
13            True if the three points form a boomerang, False otherwise
14        """
15        # Unpack the three points
16        (x1, y1), (x2, y2), (x3, y3) = points
17      
18        # Check if the three points are collinear using cross multiplication
19        # If points are collinear: (y2 - y1) / (x2 - x1) == (y3 - y2) / (x3 - x2)
20        # To avoid division by zero, we cross multiply:
21        # (y2 - y1) * (x3 - x2) == (y3 - y2) * (x2 - x1)
22        # Points form a boomerang if they are NOT collinear (inequality)
23        return (y2 - y1) * (x3 - x2) != (y3 - y2) * (x2 - x1)
24
1class Solution {
2    /**
3     * Determines if three points form a boomerang (non-collinear points).
4     * Three points form a boomerang if they are not all on the same straight line.
5     * 
6     * @param points A 2D array containing exactly 3 points, where each point is [x, y]
7     * @return true if the points form a boomerang, false if they are collinear
8     */
9    public boolean isBoomerang(int[][] points) {
10        // Extract coordinates of the first point
11        int x1 = points[0][0];
12        int y1 = points[0][1];
13      
14        // Extract coordinates of the second point
15        int x2 = points[1][0];
16        int y2 = points[1][1];
17      
18        // Extract coordinates of the third point
19        int x3 = points[2][0];
20        int y3 = points[2][1];
21      
22        // Check if the three points are collinear using the cross product method
23        // If the slopes between point1-point2 and point2-point3 are equal, they're collinear
24        // To avoid division by zero, we cross-multiply:
25        // (y2 - y1) / (x2 - x1) != (y3 - y2) / (x3 - x2)
26        // becomes: (y2 - y1) * (x3 - x2) != (y3 - y2) * (x2 - x1)
27        return (y2 - y1) * (x3 - x2) != (y3 - y2) * (x2 - x1);
28    }
29}
30
1class Solution {
2public:
3    bool isBoomerang(vector<vector<int>>& points) {
4        // Extract coordinates of the three points for better readability
5        int x1 = points[0][0], y1 = points[0][1];  // First point coordinates
6        int x2 = points[1][0], y2 = points[1][1];  // Second point coordinates
7        int x3 = points[2][0], y3 = points[2][1];  // Third point coordinates
8      
9        // Check if three points are NOT collinear using cross product
10        // If points are collinear, the slopes between point pairs are equal:
11        // (y2 - y1) / (x2 - x1) == (y3 - y2) / (x3 - x2)
12        // Cross-multiplying to avoid division by zero:
13        // (y2 - y1) * (x3 - x2) == (y3 - y2) * (x2 - x1)
14        // Return true if they form a valid boomerang (NOT collinear)
15        return (y2 - y1) * (x3 - x2) != (y3 - y2) * (x2 - x1);
16    }
17};
18
1/**
2 * Determines if three points form a boomerang (non-collinear points)
3 * A boomerang exists when three points are not in a straight line
4 * 
5 * @param points - Array of three points, each point is [x, y] coordinates
6 * @returns true if the points form a boomerang, false if they are collinear
7 */
8function isBoomerang(points: number[][]): boolean {
9    // Extract coordinates of the first point
10    const [x1, y1]: [number, number] = points[0];
11  
12    // Extract coordinates of the second point
13    const [x2, y2]: [number, number] = points[1];
14  
15    // Extract coordinates of the third point
16    const [x3, y3]: [number, number] = points[2];
17  
18    // Check if points are collinear using cross product formula
19    // If (x1-x2)*(y2-y3) = (x2-x3)*(y1-y2), points are collinear
20    // Return true when they are NOT collinear (form a boomerang)
21    return (x1 - x2) * (y2 - y3) !== (x2 - x3) * (y1 - y2);
22}
23

Time and Space Complexity

Time Complexity: O(1)

The algorithm performs a fixed number of operations regardless of input size:

  • Unpacking three coordinate pairs from the input list: O(1)
  • Computing four arithmetic operations: (y2 - y1), (x3 - x2), (y3 - y2), (x2 - x1): O(1)
  • Two multiplication operations: (y2 - y1) * (x3 - x2) and (y3 - y2) * (x2 - x1): O(1)
  • One comparison operation: !=: O(1)

Since the input always contains exactly 3 points and all operations are constant time, the overall time complexity is O(1).

Space Complexity: O(1)

The algorithm uses a fixed amount of extra space:

  • Six variables to store the unpacked coordinates: x1, y1, x2, y2, x3, y3: O(1)
  • No additional data structures are created
  • The space used does not scale with input size (which is always fixed at 3 points)

Therefore, the space complexity is O(1).

Learn more about how to find time and space complexity quickly.

Common Pitfalls

1. Attempting Direct Slope Comparison with Division

A common mistake is trying to directly calculate and compare slopes using division:

# INCORRECT APPROACH - Will fail with division by zero
def isBoomerang(self, points: List[List[int]]) -> bool:
    (x1, y1), (x2, y2), (x3, y3) = points
    slope1 = (y2 - y1) / (x2 - x1)  # Fails when x2 == x1
    slope2 = (y3 - y2) / (x3 - x2)  # Fails when x3 == x2
    return slope1 != slope2

Why it fails: When points form a vertical line or have the same x-coordinate, the denominator becomes zero, causing a runtime error.

Solution: Always use cross-multiplication to avoid division entirely, as shown in the correct implementation.

2. Incorrect Cross-Multiplication Formula

Another pitfall is mixing up the terms when cross-multiplying, leading to incorrect results:

# INCORRECT - Wrong pairing of terms
return (y2 - y1) * (x2 - x1) != (y3 - y2) * (x3 - x2)
# or
return (y2 - y1) * (y3 - y2) != (x2 - x1) * (x3 - x2)

Why it fails: These formulas don't correctly represent the slope comparison after cross-multiplication.

Solution: Remember the correct cross-multiplication pattern:

  • Original: (y2 - y1)/(x2 - x1) != (y3 - y2)/(x3 - x2)
  • Cross-multiply diagonally: (y2 - y1) * (x3 - x2) != (y3 - y2) * (x2 - x1)

3. Using Floating-Point Division for Comparison

Some might try to handle division by zero with special checks and then use floating-point comparison:

# PROBLEMATIC APPROACH
def isBoomerang(self, points: List[List[int]]) -> bool:
    (x1, y1), (x2, y2), (x3, y3) = points
  
    if x2 - x1 == 0 and x3 - x2 == 0:
        return False  # All points on same vertical line
    elif x2 - x1 == 0:
        return True   # Only first segment is vertical
    elif x3 - x2 == 0:
        return True   # Only second segment is vertical
  
    slope1 = (y2 - y1) / (x2 - x1)
    slope2 = (y3 - y2) / (x3 - x2)
    return slope1 != slope2  # Floating-point comparison issues

Why it fails:

  • Overly complex with multiple edge cases
  • Floating-point arithmetic can introduce precision errors
  • Direct equality/inequality comparison of floating-point numbers is unreliable

Solution: Stick with integer arithmetic using cross-multiplication, which avoids both division by zero and floating-point precision issues.

4. Not Considering All Collinear Cases

Some implementations might check only consecutive point pairs:

# INCOMPLETE APPROACH
def isBoomerang(self, points: List[List[int]]) -> bool:
    (x1, y1), (x2, y2), (x3, y3) = points
  
    # Only checks if first two points are different
    if x1 == x2 and y1 == y2:
        return False
  
    return (y2 - y1) * (x3 - x2) != (y3 - y2) * (x2 - x1)

Why it fails: This doesn't fully handle cases where points 2 and 3 are identical, or points 1 and 3 are identical.

Solution: The cross-multiplication formula naturally handles all duplicate point cases. When any two points are identical, the formula will evaluate to equality (making the inequality false), correctly identifying them as non-boomerang configurations.

Discover Your Strengths and Weaknesses: Take Our 5-Minute Quiz to Tailor Your Study Plan:

In a binary min heap, the minimum element can be found in:


Recommended Readings

Want a Structured Path to Master System Design Too? Don’t Miss This!

Load More