Learnitweb

LeetCode Problem 593 Valid Square


1. Problem Summary

You are given four points in a 2D plane.
Each point is represented by a pair of integers:

[x, y]

Your task is to determine whether these four points form a square, regardless of their ordering.

To be considered a valid square:

  1. All four sides must have equal non-zero length
  2. The two diagonals must have equal length
  3. Points must be distinct
  4. Shape must not collapse into a line or a point

Example interpretation:
If the points are:

[0,0], [1,1], [1,0], [0,1]

These form a perfect square → return true.


2. Key Insights

Distance comparisons are sufficient

We do not need to compute angles or slopes.
All necessary properties come from squared distances.

Use squared distances to avoid floating point math

Distance squared formula:

d² = (x1 - x2)² + (y1 - y2)²

A valid square always has:

  • exactly 4 equal smaller distances (sides)
  • exactly 2 equal larger distances (diagonals)

Reject invalid configurations

  • if any squared distance is zero → overlapping points → not a square
  • if unique distance pattern does not match 4 + 2 grouping → not a square

Order of points does not matter

Therefore we compare all pairwise distances.


3. Approach

Compute all pairwise squared distances and analyze counts

Steps:

  1. Extract the four points
  2. Compute squared distance between every pair (6 total distances)
  3. Store distances in a list
  4. Sort the list
  5. Validate:
    • first four distances equal (sides)
    • last two distances equal (diagonals)
    • side distance > 0
    • diagonal distance > side distance

If all conditions satisfied → return true
Otherwise → return false


4. Time and Space Complexity

Time Complexity: O(1)

Fixed number of operations (6 distances)

Space Complexity: O(1)

Uses constant storage


5. Java Solution

class Solution {

    private int distSq(int[] p1, int[] p2) {
        int dx = p1[0] - p2[0];
        int dy = p1[1] - p2[1];
        return dx * dx + dy * dy;
    }

    public boolean validSquare(int[] p1, int[] p2, int[] p3, int[] p4) {

        int[] distances = new int[6];

        distances[0] = distSq(p1, p2);
        distances[1] = distSq(p1, p3);
        distances[2] = distSq(p1, p4);
        distances[3] = distSq(p2, p3);
        distances[4] = distSq(p2, p4);
        distances[5] = distSq(p3, p4);

        Arrays.sort(distances);

        // Check that sides are positive and equal
        if (distances[0] == 0) return false;

        // First four should be sides, last two diagonals
        boolean sidesEqual = distances[0] == distances[1] &&
                             distances[1] == distances[2] &&
                             distances[2] == distances[3];

        boolean diagonalsEqual = distances[4] == distances[5];

        boolean diagonalGreater = distances[4] > distances[0];

        return sidesEqual && diagonalsEqual && diagonalGreater;
    }
}

6. Dry Run Examples

Example 1

Input:

p1 = [0,0]
p2 = [1,1]
p3 = [1,0]
p4 = [0,1]

Pairwise squared distances:

1,1,2,1,2,1

Sorted:

1,1,1,1,2,2

Checks:

  • first four equal → yes
  • non-zero → yes
  • last two equal → yes
  • diagonal > side → yes

Output:

true

Example 2

Input:

p1 = [0,0]
p2 = [2,0]
p3 = [3,1]
p4 = [1,1]

Distances produce unequal sides pattern

Output:

false

Example 3

Input:

p1 = [1,1]
p2 = [1,1]
p3 = [2,2]
p4 = [3,3]

Zero distances due to duplicate points

Output:

false

Example 4

Input:

p1 = [0,0]
p2 = [2,0]
p3 = [4,0]
p4 = [6,0]

All collinear

Output:

false

7. Why This Solution Works

  • Distances determine square properties uniquely
  • Avoids orientation and floating-point issues
  • Order-independent evaluation
  • Properly rules out degenerate cases
  • Applies strict geometric invariants

8. Common Mistakes

  1. Using actual Euclidean distance instead of squared → floating precision issues
  2. Assuming points arrive in order → incorrect
  3. Forgetting to check for duplicate points
  4. Misinterpreting rectangles as squares
  5. Checking slopes (unnecessary and error-prone)