You are given an array of points in the X-Y plane points where points[i] = [xi, yi].

Return the minimum area of a rectangle formed from these points, with sides parallel to the X and Y axes. If there is not any such rectangle, return 0.

&nbsp;
Example 1:

Input: points = [[1,1],[1,3],[3,1],[3,3],[2,2]]
Output: 4


Example 2:

Input: points = [[1,1],[1,3],[3,1],[3,3],[4,1],[4,3]]
Output: 2


&nbsp;
Constraints:


	1 &lt;= points.length &lt;= 500
	points[i].length == 2
	0 &lt;= xi, yi &lt;= 4 * 104
	All the given points are unique.


class Solution:
    def minAreaRect(self, points: List[List[int]]) -> int:
        points = sorted(points, key=lambda item: (item[0], item[1]))
        cols = defaultdict(list)
        
        for x,y in points:
            cols[x].append(y)
        
        lastx = {}
        ans = float('inf')
        
        for x in cols:
            col = cols[x]
            for i, y1 in enumerate(col):
                for j in range(i):
                    y2 = col[j]
                    if (y2,y1) in lastx:
                        ans = min(ans, abs((x-lastx[y2,y1])*(y2-y1)))
                    lastx[y2,y1] = x
            
        return 0 if ans==float('inf') else ans
class Solution {

    public int minAreaRect(int[][] points) {

        Map<Integer, Set<Integer>> map = new HashMap<>();

		// Group the points by x coordinates
        for (int[] point : points) {
            if (!map.containsKey(point[0])) map.put(point[0], new HashSet<>());
            map.get(point[0]).add(point[1]);
        }

        int min = Integer.MAX_VALUE;
        for (int i = 0; i < points.length - 1; i++) {

            int x1 = points[i][0];
            int y1 = points[i][1];
            for (int j = i + 1; j < points.length; j++) {
                int x2 = points[j][0];
                int y2 = points[j][1];
                if (x1 == x2 || y1 == y2) // We are looking for diagonal point, so if j is neighbour point, then continue
                    continue;

                // Note - We are calculating area first (before checking whether these points form the correct rectangle), because
                // cost of checking rectangle is very higher than calculating area. So if area less than the prev area (min), then only 
                // it makes sense to check rectangle and override min (if these points forms the correct rectangle)
                int area = Math.abs(x1 - x2) * Math.abs(y1 - y2);
                if (area < min) {
                    boolean isRectangle = map.get(x1).contains(y2) && map.get(x2).contains(y1);
                    if (isRectangle) min = area;
                }
            }
        }

        return min == Integer.MAX_VALUE ? 0 : min;
    }
}
class Solution {
public:
    int minAreaRect(vector<vector<int>>& points) {
        unordered_map<int, unordered_set<int>> pts;
        for(auto p : points)
        {
            pts[p[0]].insert(p[1]);
        }
        
        int minArea = INT_MAX;
        int n = points.size();
        for(int i=0; i<n; i++)
        {
            for(int j=i+1; j<n; j++)
            {
                auto p1 = points[i];
                auto p2 = points[j];
                if(pts[p1[0]].size()<2 || pts[p2[0]].size()<2) continue; // added to avoid extra loop
                if(p1[0]!=p2[0] && p1[1]!=p2[1]){
                    if(pts[p1[0]].count(p2[1])>0 && pts[p2[0]].count(p1[1])>0) {
                        minArea = min(minArea, (abs(p1[0]-p2[0]) * abs(p1[1]-p2[1])) );
                    }
                }
                
            }
        }
        return minArea == INT_MAX ? 0 : minArea;
    }
};
var minAreaRect = function(points) {
    const mapOfPoints = new Map();
    let minArea = Infinity;
    for(const [x,y] of points) {
        let keyString = `${x}:${y}`
        mapOfPoints.set(keyString, [x, y]);
    }
    for(const [xLeftBottom, yLeftBottom] of points) {
        for(const [xRightTop, yRightTop] of points) {
            if(!foundDiagonal(xLeftBottom, yLeftBottom, xRightTop, yRightTop)) continue;
            let leftTopCorner = `${xLeftBottom}:${yRightTop}`;
            let rightBottomCorner = `${xRightTop}:${yLeftBottom}`;
            
            if(mapOfPoints.has(leftTopCorner) && mapOfPoints.has(rightBottomCorner)) {
                const x2 = mapOfPoints.get(rightBottomCorner)[0];
                const x1 = xLeftBottom;
                const y1 = yLeftBottom;
                const y2 =  mapOfPoints.get(leftTopCorner)[1]
                const area = calculateArea(x1, x2, y1, y2);
                
                minArea = Math.min(minArea,area);
            }
        }
        
    }
    return minArea === Infinity ? 0 : minArea;
};


function calculateArea(x1, x2, y1, y2) {
    return ((x2-x1) * (y2-y1))
}

function foundDiagonal(xLeftBottom, yLeftBottom, xRightTop, yRightTop) {
    return (xRightTop > xLeftBottom && yRightTop > yLeftBottom);
}
Minimum Area Rectangle