1037. Valid Boomerang
Problem Description
Given an array points
, which contains three elements, where each element points[i] = [xi, yi]
represents a coordinate on the X-Y plane, the task is to determine if these three points constitute a boomerang. A boomerang is defined as a set of three points that comply with two conditions: first, each point must be distinct from the others; and second, the points must not lie in a straight line — that is, they shouldn't all be collinear. The function should return true
if the points form a boomerang, and false
otherwise.
Intuition
To determine whether three points (p1
, p2
, and p3
) form a boomerang, we need to ensure they are not collinear. A straightforward way to verify this is by checking if the slope between p1
and p2
is different from the slope between p2
and p3
. If both slopes are equal, the points lie on a straight line, which disqualifies them from forming a boomerang.
Mathematically, the slope between two points (x1, y1)
and (x2, y2)
is given by (y2 - y1) / (x2 - x1)
. For points not to be collinear, the slopes (y2 - y1) / (x2 - x1)
and (y3 - y2) / (x3 - x2)
should be different. To avoid division by zero, we can cross-multiply and compare the products: (y2 - y1) * (x3 - x2)
should not be equal to (y3 - y2) * (x2 - x1)
.
The solution code implements this concept by taking the three points from the points
array and calculating the products of differences as described, returning true
if they're not equal and false
otherwise. By cross-multiplying, we avoid the complication of dealing with the exact slope values or the divisions, simplifying our implementation and ensuring it remains robust even when vertical lines are involved (where the slope would be undefined).
Learn more about Math patterns.
Solution Approach
The solution to this problem involves using the formula for the slope of a line and checking if the slope of the line between the first two points (x1, y1)
and (x2, y2)
is different from the slope of the line between the second two points (x2, y2)
and (x3, y3)
.
To avoid the division operation and potential division by zero errors when calculating the slope, the implementation uses cross multiplication.
Here is the algorithm in a step-by-step fashion:
- Extract the coordinates of the three points from the input list.
- Compute the product of differences for the first and second points:
(y2 - y1) * (x3 - x2)
. - Compute the product of differences for the second and third points:
(y3 - y2) * (x2 - x1)
. - Compare the two computed products. If they are equal, it indicates that the slopes are the same and hence the points are collinear. If the products are not equal, the points are not collinear.
- Return
true
if the products are not equal (not collinear), else returnfalse
.
The above steps are represented in the given solution code:
class Solution:
def isBoomerang(self, points: List[List[int]]) -> bool:
(x1, y1), (x2, y2), (x3, y3) = points
return (y2 - y1) * (x3 - x2) != (y3 - y2) * (x2 - x1)
This code makes use of basic arithmetic operations and no additional data structures or complex patterns. It relies on the fact that if the product of the differences is equal for both pairs of points, then the three points lie on the same line (are collinear), which means they cannot form a boomerang. Otherwise, if the products are different, the points form a vertex of a non-straight line and hence do form a boomerang.
Ready to land your dream job?
Unlock your dream job with a 2-minute evaluator for a personalized learning plan!
Start EvaluatorExample Walkthrough
Let's consider an example where we have three points p1
, p2
, and p3
given by their coordinates: p1 = [1, 1]
, p2 = [2, 3]
, and p3 = [3, 2]
. We want to find out if these points form a boomerang.
Using the provided solution approach, we will take the following steps:
-
Extract the coordinates of the three points from the input list. We already have that as:
p1
(x1, y1) = (1, 1)p2
(x2, y2) = (2, 3)p3
(x3, y3) = (3, 2)
-
Compute the product of differences for the first and second points:
(y2 - y1) * (x3 - x2)
, which will be:(3 - 1) * (3 - 2) = 2 * 1 = 2
-
Compute the product of differences for the second and third points:
(y3 - y2) * (x2 - x1)
, which will be:(2 - 3) * (2 - 1) = -1 * 1 = -1
-
Compare the two computed products. In our example,
2
is not equal to-1
, indicating that the slopes are different, and hence the points are not collinear. -
Since the products are not equal, we return
true
, concluding that the pointsp1
,p2
, andp3
do indeed form a boomerang.
To summarize, the points (1, 1), (2, 3), and (3, 2) when plugged into our solution approach show that they are not collinear and hence form a boomerang. The function will return true
in this case.
Solution Implementation
1from typing import List
2
3class Solution:
4 def isBoomerang(self, points: List[List[int]]) -> bool:
5 # Extract the individual points for clarity
6 point1, point2, point3 = points
7
8 # Destructure the points into their respective x and y coordinates
9 x1, y1 = point1
10 x2, y2 = point2
11 x3, y3 = point3
12
13 # A boomerang is defined as a set of three points that are not in a straight line.
14 # To determine if points are not in a straight line, the slope between points 1 and 2
15 # must be different from the slope between points 2 and 3.
16
17 # Calculate the slope between point1 and point2 (slope = (y2-y1)/(x2-x1))
18 # Calculate the slope between point2 and point3 (slope = (y3-y2)/(x3-x2))
19 # To avoid division by zero in slope calculations, compare the cross multiplication of
20 # the differences in y-coordinates and x-coordinates instead.
21
22 # A boomerang should meet the condition:
23 # (y2 - y1)/(x2 - x1) != (y3 - y2)/(x3 - x2)
24 # which simplifies to avoiding floating point precision comparison as:
25 # (y2 - y1) * (x3 - x2) != (y3 - y2) * (x2 - x1)
26
27 # Check if the slopes are different, if so, it is a boomerang
28 return (y2 - y1) * (x3 - x2) != (y3 - y2) * (x2 - x1)
29
30# Example usage:
31# sol = Solution()
32# print(sol.isBoomerang([[1,1], [2,3], [3,2]])) # Outputs: True, since the points form a boomerang
33
1class Solution {
2 public boolean isBoomerang(int[][] points) {
3 // Extracting coordinates for better readability
4 int x1 = points[0][0], y1 = points[0][1];
5 int x2 = points[1][0], y2 = points[1][1];
6 int x3 = points[2][0], y3 = points[2][1];
7
8 // A boomerang is a set of three points that are all distinct and not in a straight line.
9 // Check if the slopes between points p1 & p2 and points p2 & p3 are different.
10 // Slope of line p1 and p2 is (y2 - y1)/(x2 - x1) and slope of line p2 and p3 is (y3 - y2)/(x3 - x2).
11 // To avoid division (which can lead to division by zero) we cross-multiply to compare the slopes.
12 return (y2 - y1) * (x3 - x2) != (y3 - y2) * (x2 - x1);
13 }
14}
15
1#include <vector> // Include necessary header for the use of vector
2
3class Solution {
4public:
5 bool isBoomerang(std::vector<std::vector<int>>& points) {
6 // Extract coordinates of the first point
7 int x1 = points[0][0];
8 int y1 = points[0][1];
9
10 // Extract coordinates of the second point
11 int x2 = points[1][0];
12 int y2 = points[1][1];
13
14 // Extract coordinates of the third point
15 int x3 = points[2][0];
16 int y3 = points[2][1];
17
18 // Check if the slope of the line formed by point 1 and point 2 is different
19 // from the slope of the line formed by point 2 and point 3.
20 // If slopes are different, points are non-collinear, thus returning true.
21 return (y2 - y1) * (x3 - x2) != (y3 - y2) * (x2 - x1);
22 }
23};
24
1// This function checks if three points form a boomerang (a set of three points that are all distinct from each
2// other and do not lie on the same line).
3function isBoomerang(points: number[][]): boolean {
4 // Destructuring the first point into x1 and y1
5 const [x1, y1] = points[0];
6 // Destructuring the second point into x2 and y2
7 const [x2, y2] = points[1];
8 // Destructuring the third point into x3 and y3
9 const [x3, y3] = points[2];
10
11 // Compute the slopes of the lines (x1,y1) -> (x2,y2) and (x2,y2) -> (x3,y3)
12 // If the slopes are not equal, the points are non-collinear which means they form a boomerang.
13 // To avoid division (and possible division by zero), cross-multiplication is used to compare the slopes:
14 // slope of (x1,y1) -> (x2,y2) is (y2-y1)/(x2-x1)
15 // slope of (x2,y2) -> (x3,y3) is (y3-y2)/(x3-x2)
16 // We compare (y2-y1)*(x3-x2) with (y3-y2)*(x2-x1)
17 return (x1 - x2) * (y2 - y3) !== (x2 - x3) * (y1 - y2);
18}
19
Time and Space Complexity
The time complexity of the given code is O(1)
because the operations performed are constant and do not depend on the size of the input; the code always handles exactly three points.
The space complexity of the code is O(1)
as well, since the space used does not scale with the input. The only additional space used is for the unpacked point coordinates, which is a constant amount of space for the three pairs of integers.
Learn more about how to find time and space complexity quickly using problem constraints.
What's the output of running the following function using input [30, 20, 10, 100, 33, 12]
?
1def fun(arr: List[int]) -> List[int]:
2 import heapq
3 heapq.heapify(arr)
4 res = []
5 for i in range(3):
6 res.append(heapq.heappop(arr))
7 return res
8
1public static int[] fun(int[] arr) {
2 int[] res = new int[3];
3 PriorityQueue<Integer> heap = new PriorityQueue<>();
4 for (int i = 0; i < arr.length; i++) {
5 heap.add(arr[i]);
6 }
7 for (int i = 0; i < 3; i++) {
8 res[i] = heap.poll();
9 }
10 return res;
11}
12
1class HeapItem {
2 constructor(item, priority = item) {
3 this.item = item;
4 this.priority = priority;
5 }
6}
7
8class MinHeap {
9 constructor() {
10 this.heap = [];
11 }
12
13 push(node) {
14 // insert the new node at the end of the heap array
15 this.heap.push(node);
16 // find the correct position for the new node
17 this.bubble_up();
18 }
19
20 bubble_up() {
21 let index = this.heap.length - 1;
22
23 while (index > 0) {
24 const element = this.heap[index];
25 const parentIndex = Math.floor((index - 1) / 2);
26 const parent = this.heap[parentIndex];
27
28 if (parent.priority <= element.priority) break;
29 // if the parent is bigger than the child then swap the parent and child
30 this.heap[index] = parent;
31 this.heap[parentIndex] = element;
32 index = parentIndex;
33 }
34 }
35
36 pop() {
37 const min = this.heap[0];
38 this.heap[0] = this.heap[this.size() - 1];
39 this.heap.pop();
40 this.bubble_down();
41 return min;
42 }
43
44 bubble_down() {
45 let index = 0;
46 let min = index;
47 const n = this.heap.length;
48
49 while (index < n) {
50 const left = 2 * index + 1;
51 const right = left + 1;
52
53 if (left < n && this.heap[left].priority < this.heap[min].priority) {
54 min = left;
55 }
56 if (right < n && this.heap[right].priority < this.heap[min].priority) {
57 min = right;
58 }
59 if (min === index) break;
60 [this.heap[min], this.heap[index]] = [this.heap[index], this.heap[min]];
61 index = min;
62 }
63 }
64
65 peek() {
66 return this.heap[0];
67 }
68
69 size() {
70 return this.heap.length;
71 }
72}
73
74function fun(arr) {
75 const heap = new MinHeap();
76 for (const x of arr) {
77 heap.push(new HeapItem(x));
78 }
79 const res = [];
80 for (let i = 0; i < 3; i++) {
81 res.push(heap.pop().item);
82 }
83 return res;
84}
85
Recommended Readings
Math for Technical Interviews How much math do I need to know for technical interviews The short answer is about high school level math Computer science is often associated with math and some universities even place their computer science department under the math faculty However the reality is that you
LeetCode Patterns Your Personal Dijkstra's Algorithm to Landing Your Dream Job The goal of AlgoMonster is to help you get a job in the shortest amount of time possible in a data driven way We compiled datasets of tech interview problems and broke them down by patterns This way we
Recursion Recursion is one of the most important concepts in computer science Simply speaking recursion is the process of a function calling itself Using a real life analogy imagine a scenario where you invite your friends to lunch https algomonster s3 us east 2 amazonaws com recursion jpg You first
Want a Structured Path to Master System Design Too? Don’t Miss This!