Given the coordinates of four points in 2D space p1
, p2
, p3
and p4
, return true
if the four points construct a square. The coordinate of a point pᵢ
is represented as [xᵢ, yᵢ]
. The input is not given in any order. A valid square has four equal sides with positive length and four equal angles (90-degree angles).
Example:
Input: p1 = [0,0], p2 = [1,1], p3 = [1,0], p4 = [0,1] Output: true
Clarifications:
A naive approach to solving this problem would be to calculate the distance between every pair of points. For four points to form a square, we need to verify that there are four sides of equal length and two diagonals of equal length. Also, we need to ensure that the side length is not zero, and the points are distinct.
import math
def distance(p1, p2):
return math.sqrt((p1[0] - p2[0])**2 + (p1[1] - p2[1])**2)
def is_square_brute_force(p1, p2, p3, p4):
distances = []
points = [p1, p2, p3, p4]
for i in range(4):
for j in range(i + 1, 4):
distances.append(distance(points[i], points[j]))
distances.sort()
# Check for equal sides and equal diagonals
if distances[0] > 0 and \
abs(distances[0] - distances[1]) < 1e-6 and \
abs(distances[0] - distances[2]) < 1e-6 and \
abs(distances[0] - distances[3]) < 1e-6 and \
abs(distances[4] - distances[5]) < 1e-6 and \
abs(distances[4] / distances[0] - math.sqrt(2)) < 1e-6:
return True
return False
O(1) because we have a fixed number of calculations.
O(1) because we use a fixed amount of extra space.
An optimized approach still calculates distances but does so more strategically. We can use a set
to store the distances to ensure we don't have zero length sides or duplicate points. Then, we verify if the count of unique distances are 2. The larger distance must be sqrt(2)
times of the smaller distance to form a square.
set
.sqrt(2)
import math
def distance(p1, p2):
return math.sqrt((p1[0] - p2[0])**2 + (p1[1] - p2[1])**2)
def is_square(p1, p2, p3, p4):
distances = set()
points = [p1, p2, p3, p4]
for i in range(4):
for j in range(i + 1, 4):
dist = distance(points[i], points[j])
if dist == 0:
return False # handles duplicate points
distances.add(dist)
if len(distances) != 2:
return False
distances = sorted(list(distances))
if abs(distances[1] / distances[0] - math.sqrt(2)) < 1e-6:
return True
return False
O(1) because we have a fixed number of calculations regardless of the input size.
O(1) because the set will hold a maximum of two distinct distances.