LeetCodee

593. Valid Square

Jump to Solution: Python Java C++ JavaScript C#

Problem Description

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 pi is represented as [xi, yi]. The input is not guaranteed to be in any specific order.

A valid square has four equal sides with positive length and four equal angles (90-degree angles).

Example 1:

Input: p1 = [0,0], p2 = [1,1], p3 = [1,0], p4 = [0,1]
Output: true

Example 2:

Input: p1 = [0,0], p2 = [1,1], p3 = [1,0], p4 = [0,12]
Output: false

Example 3:

Input: p1 = [1,0], p2 = [-1,0], p3 = [0,1], p4 = [0,-1]
Output: true

Constraints:

  • p1.length == p2.length == p3.length == p4.length == 2
  • -104 <= xi, yi <= 104

Solution

Python Solution

class Solution:
    def validSquare(self, p1: List[int], p2: List[int], p3: List[int], p4: List[int]) -> bool:
        def dist(p1: List[int], p2: List[int]) -> int:
            return (p1[0] - p2[0]) * (p1[0] - p2[0]) + (p1[1] - p2[1]) * (p1[1] - p2[1])
        
        points = [p1, p2, p3, p4]
        distances = set()
        
        for i in range(4):
            for j in range(i + 1, 4):
                d = dist(points[i], points[j])
                if d == 0:  # Points cannot be the same
                    return False
                distances.add(d)
                
        # A square has 4 equal sides and 2 equal diagonals
        return len(distances) == 2

Time Complexity: O(1)

Since we always process 4 points.

Space Complexity: O(1)

We store at most 6 distances.

Java Solution

class Solution {
    private int dist(int[] p1, int[] p2) {
        return (p1[0] - p2[0]) * (p1[0] - p2[0]) + (p1[1] - p2[1]) * (p1[1] - p2[1]);
    }
    
    public boolean validSquare(int[] p1, int[] p2, int[] p3, int[] p4) {
        int[][] points = {p1, p2, p3, p4};
        Set distances = new HashSet<>();
        
        for (int i = 0; i < 4; i++) {
            for (int j = i + 1; j < 4; j++) {
                int d = dist(points[i], points[j]);
                if (d == 0) {  // Points cannot be the same
                    return false;
                }
                distances.add(d);
            }
        }
        
        // A square has 4 equal sides and 2 equal diagonals
        return distances.size() == 2;
    }
}

Time Complexity: O(1)

Since we always process 4 points.

Space Complexity: O(1)

We store at most 6 distances.

C++ Solution

class Solution {
private:
    int dist(vector& p1, vector& p2) {
        return (p1[0] - p2[0]) * (p1[0] - p2[0]) + (p1[1] - p2[1]) * (p1[1] - p2[1]);
    }
    
public:
    bool validSquare(vector& p1, vector& p2, vector& p3, vector& p4) {
        vector> points = {p1, p2, p3, p4};
        unordered_set distances;
        
        for (int i = 0; i < 4; i++) {
            for (int j = i + 1; j < 4; j++) {
                int d = dist(points[i], points[j]);
                if (d == 0) {  // Points cannot be the same
                    return false;
                }
                distances.insert(d);
            }
        }
        
        // A square has 4 equal sides and 2 equal diagonals
        return distances.size() == 2;
    }
};

Time Complexity: O(1)

Since we always process 4 points.

Space Complexity: O(1)

We store at most 6 distances.

JavaScript Solution

/**
 * @param {number[]} p1
 * @param {number[]} p2
 * @param {number[]} p3
 * @param {number[]} p4
 * @return {boolean}
 */
var validSquare = function(p1, p2, p3, p4) {
    const dist = (p1, p2) => {
        return (p1[0] - p2[0]) * (p1[0] - p2[0]) + (p1[1] - p2[1]) * (p1[1] - p2[1]);
    };
    
    const points = [p1, p2, p3, p4];
    const distances = new Set();
    
    for (let i = 0; i < 4; i++) {
        for (let j = i + 1; j < 4; j++) {
            const d = dist(points[i], points[j]);
            if (d === 0) {  // Points cannot be the same
                return false;
            }
            distances.add(d);
        }
    }
    
    // A square has 4 equal sides and 2 equal diagonals
    return distances.size === 2;
};

Time Complexity: O(1)

Since we always process 4 points.

Space Complexity: O(1)

We store at most 6 distances.

C# Solution

public class Solution {
    private int Dist(int[] p1, int[] p2) {
        return (p1[0] - p2[0]) * (p1[0] - p2[0]) + (p1[1] - p2[1]) * (p1[1] - p2[1]);
    }
    
    public bool ValidSquare(int[] p1, int[] p2, int[] p3, int[] p4) {
        int[][] points = new int[][] { p1, p2, p3, p4 };
        var distances = new HashSet();
        
        for (int i = 0; i < 4; i++) {
            for (int j = i + 1; j < 4; j++) {
                int d = Dist(points[i], points[j]);
                if (d == 0) {  // Points cannot be the same
                    return false;
                }
                distances.Add(d);
            }
        }
        
        // A square has 4 equal sides and 2 equal diagonals
        return distances.Count == 2;
    }
}

Time Complexity: O(1)

Since we always process 4 points.

Space Complexity: O(1)

We store at most 6 distances.

Approach Explanation

The solution uses distance-based validation:

  1. Key Insights:
    • Square properties
    • Distance calculation
    • Set of distances
    • Equal sides
  2. Algorithm Steps:
    • Calculate distances
    • Check duplicates
    • Validate count
    • Handle edge cases

Implementation Details:

  • Distance function
  • Point comparison
  • Set operations
  • Validation logic

Optimization Insights:

  • Early return
  • No sorting needed
  • Constant space
  • Efficient checks

Edge Cases:

  • Same points
  • Line formation
  • Rectangle
  • Rhombus