Separate Squares I

Medium
Watch on YouTube ↗

Solution

class Solution {

    // Finds the horizontal y = k line that splits the total square area into two equal halves
    public double separateSquares(int[][] squares) {

        // left  → lowest possible y-coordinate where the cut can be
        // right → highest possible y-coordinate where the cut can be
        double left = Double.MAX_VALUE, right = 0;

        // total area of all squares combined
        double totalArea = 0.0;

        // Step 1: Determine search space and total area
        // Time: O(n)
        for (int[] square : squares) {

            // y-coordinate of bottom edge of square
            double y = square[1];

            // side length of square
            double side = square[2];

            // add square's full area
            totalArea += side * side;

            // lowest possible cut line
            left = Math.min(left, y);

            // highest possible cut line (top edge of square)
            right = Math.max(right, y + side);
        }

        // Step 2: Binary search to find y such that
        // area above the line == area below the line
        // Each iteration computes area in O(n)
        while (right - left > 1e-5) {

            // candidate y-line
            double mid = (left + right) / 2.0;

            // area above y = mid
            double aboveArea = getArea(mid, squares);

            // area below y = mid
            double belowArea = totalArea - aboveArea;

            // If area above is larger, move the cut upward
            if (aboveArea > belowArea) {
                left = mid;
            }
            // Otherwise, move the cut downward
            else {
                right = mid;
            }
        }

        // left (or right) converges to the required y-coordinate
        return left;
    }

    // Computes total area of square parts lying ABOVE y = yline
    // Time: O(n)
    double getArea(double yline, int[][] squares) {

        double area = 0.0;

        for (int[] square : squares) {

            double y = square[1];     // bottom edge
            double side = square[2];  // side length

            // Case 1: Square is fully above the cut
            if (y >= yline) {
                area += side * side;
            }

            // Case 2: Square is partially above the cut
            else if (y + side > yline) {
                area += (y + side - yline) * side;
            }

            // Case 3: Square is fully below the cut → contributes 0
        }

        return area;
    }
}