LeetCode 963 - Minimum Area Rectangle II


Related:
LeetCode 223 - Rectangle Area
LeetCode 850 - Rectangle Area II
LeetCode 939 - Minimum Area Rectangle
LeetCode 963 - Minimum Area Rectangle II
https://leetcode.com/problems/minimum-area-rectangle-ii/
Given a set of points in the xy-plane, determine the minimum area of any rectangle formed from these points, with sides not necessarily parallel to the x and y axes.
If there isn't any rectangle, return 0.

Example 1:
Input: [[1,2],[2,1],[1,0],[0,1]]
Output: 2.00000
Explanation: The minimum area rectangle occurs at [1,2],[2,1],[1,0],[0,1], with an area of 2.
Example 2:
Input: [[0,1],[2,1],[1,1],[1,0],[2,0]]
Output: 1.00000
Explanation: The minimum area rectangle occurs at [1,0],[1,1],[2,1],[2,0], with an area of 1.
Example 3:
Input: [[0,3],[1,2],[3,1],[1,3],[2,1]]
Output: 0
Explanation: There is no possible rectangle to form from these points.
Example 4:
Input: [[3,1],[1,1],[0,1],[2,1],[3,3],[3,2],[0,2],[2,3]]
Output: 2.00000
Explanation: The minimum area rectangle occurs at [2,1],[2,3],[3,3],[3,1], with an area of 2.

Note:
  1. 1 <= points.length <= 50
  2. 0 <= points[i][0] <= 40000
  3. 0 <= points[i][1] <= 40000
  4. All points are distinct.
  5. Answers within 10^-5 of the actual value will be accepted as correct
https://blog.csdn.net/lwgkzl/article/details/85221883


长方形判定定理:对角线相等,且互相平分的四边形是矩形。

首先平方枚举两个点所构成的所有线段。

对于这些线段把它们当做长方形的一条对角线,确定了这条对角线之后。

枚举第三个点,首先判断第三个点到对角线中点的距离是不是满足对角线长度的一半,(比较距离)

然后判断,与这三个点构成矩形的第四个点是不是存在:讲解一

如果以上两个判断都成立,那么算该长方形的面积(四个点都有了,算出长宽之积就ok)

然后用一个全局变量存满足条件的矩形的最小值就好。

讲解一:

如果判断第四个点存不存在呢?假设p1,p2,p3是已知的三个点。p1,p2构成对角线,对角线的中点是(a,b)

那么第四个点的坐标为:p3.x + (p3.x - a),p3.y + (p3.y - b).其中p3.x-a是p3到中点X轴方向的L1距离,仔细体会一下~

然后用一个map存一下所有的点就可以判断这个点在不在集合内了。



X. https://zhanghuimeng.github.io/post/leetcode-963-minimum-area-rectangle-ii/
枚举圆心和半径
    double minAreaFreeRect(vector<vector<int>>& points) {
        map<pair<Point, int>, vector<int>> mmap;
        vector<Point> p;
        int N = points.size();
        for (int i = 0; i < N; i++)
            p.emplace_back(points[i][0], points[i][1]);
        sort(p.begin(), p.end());
        for (int i = 0; i < N; i++)
            for (int j = i + 1; j < N; j++) {
                Vector v = p[j] - p[i];
                mmap[make_pair((p[i] + p[j]) / 2, v.length2())].push_back(i);
            }
        double ans = -1;
        for (const auto& pa: mmap) {
            Point center = pa.first.first;
            for (int i = 0; i < pa.second.size(); i++) {
                // cout << pa.second[i] << ' ';
                for (int j = i + 1; j < pa.second.size(); j++) {
                    int i1 = pa.second[i], j1 = pa.second[j]; 
                    double area = 2 * abs(cross(p[i1] - center, p[j1] - center));
                    ans = ans < 0 ? area : min(ans, area);
                }
            }
        }
        return max(ans, 0.0);
    }
https://jinx19.github.io/2018/12/24/LeetCode-Solution-2018-12-24-LeetCode-Solution-963-Minimum-Area-Rectangle-II/
考虑矩形ABCD的对角点AC和BD,它们有相同的中心O,即AC的中点和AB的中点;并且它们都具有相同的半径dist(O,A)== dist(O,B)== dist(O,C)== dist(O,D)。
在该结果的推动下,让我们将每对点PQ分类为它们的中心C = PQ的中点,并且半径r = dist(P,C)。我们的策略是对具有相同分类的成对点进行暴力破解。
对于每对点,按中心和半径对它们进行分类。我们只需要记录其中一个点P,因为另一个点是P’= 2 * center-P(使用矢量符号)。
对于每个中心和半径,查看每个可能的矩形(两对点P,P’,Q,Q’)。该矩形dist(P,Q)* dist(P,Q’)的面积是候选答案。

https://leetcode.com/articles/minimum-area-rectangle-ii/
Approach 2: Iterate Centers
  • Time Complexity: O(N^2 \log N), where N is the length of points. It can be shown that the number of pairs of points with the same classification is bounded by \log N - see this link for more.
  • Space Complexity: O(N).
Consider opposite points AC and BD of a rectangle ABCD. They both have the same center O, which is the midpoint of AC and the midpoint of AB; and they both have the same radius dist(O, A) == dist(O, B) == dist(O, C) == dist(O, D). Notice that a necessary and sufficient condition to form a rectangle with two opposite pairs of points is that the points must have the same center and radius.
Motivated by that result, let's classify each pair of points PQ by their center C = the midpoint of PQ, and the radius r = dist(P, C). Our strategy is to brute force on pairs of points with the same classification.
Algorithm
For each pair of points, classify them by center and radius. We only need to record one of the points P, since the other point is P' = 2 * center - P (using vector notation).
For each center and radius, look at every possible rectangle (two pairs of points P, P', Q, Q'). The area of this rectangle dist(P, Q) * dist(P, Q') is a candidate answer.
  public double minAreaFreeRect(int[][] points) {
    int N = points.length;
    Point[] A = new Point[N];
    for (int i = 0; i < N; ++i)
      A[i] = new Point(points[i][0], points[i][1]);

    Map<Integer, Map<Point, List<Point>>> seen = new HashMap();
    for (int i = 0; i < N; ++i)
      for (int j = i + 1; j < N; ++j) {
        // center is twice actual to keep integer precision
        Point center = new Point(A[i].x + A[j].x, A[i].y + A[j].y);

        int r2 = (A[i].x - A[j].x) * (A[i].x - A[j].x);
        r2 += (A[i].y - A[j].y) * (A[i].y - A[j].y);
        if (!seen.containsKey(r2))
          seen.put(r2, new HashMap<Point, List<Point>>());
        if (!seen.get(r2).containsKey(center))
          seen.get(r2).put(center, new ArrayList<Point>());
        seen.get(r2).get(center).add(A[i]);
      }

    double ans = Double.MAX_VALUE;
    for (Map<Point, List<Point>> info : seen.values()) {
      for (Point center : info.keySet()) { // center is twice actual
        List<Point> candidates = info.get(center);
        int clen = candidates.size();
        for (int i = 0; i < clen; ++i)
          for (int j = i + 1; j < clen; ++j) {
            Point P = candidates.get(i);
            Point Q = candidates.get(j);
            Point Q2 = new Point(center);
            Q2.translate(-Q.x, -Q.y);
            double area = P.distance(Q) * P.distance(Q2);
            if (area < ans)
              ans = area;
          }
      }
    }

    return ans < Double.MAX_VALUE ? ans : 0;

  }

For each triangle, let's try to find the 4th point and whether it is a rectangle.
Say the first 3 points are p1, p2, p3, and that p2 and p3 are opposite corners of the final rectangle. The 4th point must be p4 = p2 + p3 - p1 (using vector notation) because p1, p2, p4, p3 must form a parallelogram, and p1 + (p2 - p1) + (p3 - p1) = p4.
If this point exists in our collection (we can use a HashSet to check), then we should check that the angles of this parallelogram are 90 degrees. The easiest way is to check the dot product of the two vectors (p2 - p1) and (p3 - p1). (Another way is we could normalize the vectors to length 1, and check that one equals the other rotated by 90 degrees.)
  • Time Complexity: O(N^3), where N is the length of points.
  public double minAreaFreeRect(int[][] points) {
    int N = points.length;

    Point[] A = new Point[N];
    Set<Point> pointSet = new HashSet();
    for (int i = 0; i < N; ++i) {
      A[i] = new Point(points[i][0], points[i][1]);
      pointSet.add(A[i]);
    }

    double ans = Double.MAX_VALUE;
    for (int i = 0; i < N; ++i) {
      Point p1 = A[i];
      for (int j = 0; j < N; ++j)
        if (j != i) {
          Point p2 = A[j];
          for (int k = j + 1; k < N; ++k)
            if (k != i) {
              Point p3 = A[k];
              Point p4 = new Point(p2.x + p3.x - p1.x, p2.y + p3.y - p1.y);

              if (pointSet.contains(p4)) {
                int dot = ((p2.x - p1.x) * (p3.x - p1.x) + (p2.y - p1.y) * (p3.y - p1.y));
                if (dot == 0) {
                  double area = p1.distance(p2) * p1.distance(p3);
                  if (area < ans)
                    ans = area;
                }
              }
            }
        }
    }

    return ans < Double.MAX_VALUE ? ans : 0;

  }

X. O(N^3)

如果p4在集合内,则检查对角线的角度是否为90度,即是否为正方形。
最简单的方法是检查角度, 利用直角三角形的特性:两直角边边长的平方和等于斜边长的平方
最简单的方法是检查两个向量(p2 - p1)和(p3 - p1)的点积
两向量内积为0说明向量垂直

http://www.programmersought.com/article/5527381097/
    public double minAreaFreeRect(int[][] points) {
        Set<String> set = new HashSet<>();
        double result = Double.MAX_VALUE;
        // construct point set
        for(int[] p : points){
            set.add(p[0] + " " + p[1]);
        }
        / / Through the third point to find the fourth point
        for(int[] p1 : points){
            for(int[] p2 : points){
                if(p1[0] == p2[0] && p1[1] == p2[1]){
                    continue;
                }
                for(int[] p3 : points){
                    / / Pythagorean
                    if(dist(p1, p3) + dist(p2, p3) != dist(p1, p2)){
                        continue;
                    }
                    / / The coordinates of the fourth point
                    int x = p1[0] + p2[0] - p3[0];
                    int y = p1[1] + p2[1] - p3[1];
                    / / Whether the fourth point exists in the point set
                    if(!set.contains(x + " " + y)){
                        continue;
                    }
                    double area = Math.sqrt(dist(p1, p3)) * Math.sqrt(dist(p2, p3));
                    if(area == 0){
                        continue;
                    }
                    result = Math.min(result, area);
                }
            }
        }
        return result == Double.MAX_VALUE ? 0 : result;
    }
    public double dist(int[] x1, int[] x2){
        return (x1[0] - x2[0]) * (x1[0] - x2[0]) + (x1[1] - x2[1]) * (x1[1] - x2[1]);
    }
}
    (枚举) O(n3)O(n3)
    将所有点加入哈希表中。
    每次枚举三个点 x, y, z,以这三个点尝试构成矩形的一组邻边,共有三种情况。假设 (x, y) 和 (x, z) 构成一组邻边,判定其是否垂直,即点乘为 0。然后,通过向量运算求出另一个点 p,使得 (x, y) 与 (z, p) 是相同的向量。在哈希表中判断 p 是否存在即可。
    https://leetcode.com/problems/minimum-area-rectangle-ii/discuss/208377/Python-easy-to-understand-dot-product-O(N3)-AC
    • Dot product of two sides in a rectangle should be zero because a . b = |a| |b| cos(90)
    • If we can extend p3 by the same margin delta(p2 - p1), we can have the fourth point p4.
      • x4 = x3 + (x2 - x1)
      • y4 = y3 + (y2 - y1)
    • If p4 in points, calculate area.
    https://leetcode.com/problems/minimum-area-rectangle-ii/discuss/208361/JAVA-O(n2)-using-Map
    In the worst case it is still O(N^3): simply consider all diagonal bisect each other and of equal length.
    1. Two diagonals of a rectangle bisect each other, and are of equal length.
    2. The map's key is String including diagonal length and coordinate of the diagonal center; map's value is the index of two points forming the diagonal
        public double minAreaFreeRect(int[][] points) {
            int len = points.length;
            double res = Double.MAX_VALUE;
            if (len < 4) return 0.0;
            Map<String, List<int[]>> map = new HashMap<>(); // int[] is the index of two points forming the diagonal
            for (int i = 0; i < len; i++) {
                for (int j = i + 1; j < len; j++) {
                    long dis = (points[i][0] - points[j][0]) * (points[i][0] - points[j][0]) + (points[i][1] - points[j][1]) * (points[i][1] - points[j][1]);
                    double centerX = (double)(points[j][0] + points[i][0])/2; // centerX and centerY is the coordinate of the diagonal center
                    double centerY = (double)(points[j][1] + points[i][1])/2;
                    String key = "" + dis + "+" + centerX + "+" + centerY; // key includes the length of the diagonal and the coordinate of the diagonal center
                    if (map.get(key) == null) map.put(key, new ArrayList<int[]>());
                    map.get(key).add(new int[]{i,j});
                }
            }
            for (String key : map.keySet()) {
                if (map.get(key).size() > 1) {  
                    List<int[]> list = map.get(key);
                    for (int i = 0; i < list.size(); i++) { // there could be multiple rectangles inside
                        for (int j = i + 1; j < list.size(); j++) {
                            int p1 = list.get(i)[0]; // p1, p2 and p3 are the three vertices of a rectangle
                            int p2 = list.get(j)[0];
                            int p3 = list.get(j)[1];
                            // len1 and len2 are the length of the sides of a rectangle
                            double len1 = Math.sqrt((points[p1][0] - points[p2][0]) * (points[p1][0] - points[p2][0]) +  (points[p1][1] - points[p2][1]) * (points[p1][1] - points[p2][1])); 
                            double len2 = Math.sqrt((points[p1][0] - points[p3][0]) * (points[p1][0] - points[p3][0]) +  (points[p1][1] - points[p3][1]) * (points[p1][1] - points[p3][1]));
                            double area = len1 * len2; 
                            res = Math.min(res, area);
                        }
                    }
                }
            }
            return res == Double.MAX_VALUE ?  0.0 : res;
        }
    

    Labels

    LeetCode (1432) GeeksforGeeks (1122) LeetCode - Review (1067) Review (882) Algorithm (668) to-do (609) Classic Algorithm (270) Google Interview (237) Classic Interview (222) Dynamic Programming (220) DP (186) Bit Algorithms (145) POJ (141) Math (137) Tree (132) LeetCode - Phone (129) EPI (122) Cracking Coding Interview (119) DFS (115) Difficult Algorithm (115) Lintcode (115) Different Solutions (110) Smart Algorithm (104) Binary Search (96) BFS (91) HackerRank (90) Binary Tree (86) Hard (79) Two Pointers (78) Stack (76) Company-Facebook (75) BST (72) Graph Algorithm (72) Time Complexity (69) Greedy Algorithm (68) Interval (63) Company - Google (62) Geometry Algorithm (61) Interview Corner (61) LeetCode - Extended (61) Union-Find (60) Trie (58) Advanced Data Structure (56) List (56) Priority Queue (53) Codility (52) ComProGuide (50) LeetCode Hard (50) Matrix (50) Bisection (48) Segment Tree (48) Sliding Window (48) USACO (46) Space Optimization (45) Company-Airbnb (41) Greedy (41) Mathematical Algorithm (41) Tree - Post-Order (41) ACM-ICPC (40) Algorithm Interview (40) Data Structure Design (40) Graph (40) Backtracking (39) Data Structure (39) Jobdu (39) Random (39) Codeforces (38) Knapsack (38) LeetCode - DP (38) Recursive Algorithm (38) String Algorithm (38) TopCoder (38) Sort (37) Introduction to Algorithms (36) Pre-Sort (36) Beauty of Programming (35) Must Known (34) Binary Search Tree (33) Follow Up (33) prismoskills (33) Palindrome (32) Permutation (31) Array (30) Google Code Jam (30) HDU (30) Array O(N) (29) Logic Thinking (29) Monotonic Stack (29) Puzzles (29) Code - Detail (27) Company-Zenefits (27) Microsoft 100 - July (27) Queue (27) Binary Indexed Trees (26) TreeMap (26) to-do-must (26) 1point3acres (25) GeeksQuiz (25) Merge Sort (25) Reverse Thinking (25) hihocoder (25) Company - LinkedIn (24) Hash (24) High Frequency (24) Summary (24) Divide and Conquer (23) Proof (23) Game Theory (22) Topological Sort (22) Lintcode - Review (21) Tree - Modification (21) Algorithm Game (20) CareerCup (20) Company - Twitter (20) DFS + Review (20) DP - Relation (20) Brain Teaser (19) DP - Tree (19) Left and Right Array (19) O(N) (19) Sweep Line (19) UVA (19) DP - Bit Masking (18) LeetCode - Thinking (18) KMP (17) LeetCode - TODO (17) Probabilities (17) Simulation (17) String Search (17) Codercareer (16) Company-Uber (16) Iterator (16) Number (16) O(1) Space (16) Shortest Path (16) itint5 (16) DFS+Cache (15) Dijkstra (15) Euclidean GCD (15) Heap (15) LeetCode - Hard (15) Majority (15) Number Theory (15) Rolling Hash (15) Tree Traversal (15) Brute Force (14) Bucket Sort (14) DP - Knapsack (14) DP - Probability (14) Difficult (14) Fast Power Algorithm (14) Pattern (14) Prefix Sum (14) TreeSet (14) Algorithm Videos (13) Amazon Interview (13) Basic Algorithm (13) Codechef (13) Combination (13) Computational Geometry (13) DP - Digit (13) LCA (13) LeetCode - DFS (13) Linked List (13) Long Increasing Sequence(LIS) (13) Math-Divisible (13) Reservoir Sampling (13) mitbbs (13) Algorithm - How To (12) Company - Microsoft (12) DP - Interval (12) DP - Multiple Relation (12) DP - Relation Optimization (12) LeetCode - Classic (12) Level Order Traversal (12) Prime (12) Pruning (12) Reconstruct Tree (12) Thinking (12) X Sum (12) AOJ (11) Bit Mask (11) Company-Snapchat (11) DP - Space Optimization (11) Dequeue (11) Graph DFS (11) MinMax (11) Miscs (11) Princeton (11) Quick Sort (11) Stack - Tree (11) 尺取法 (11) 挑战程序设计竞赛 (11) Coin Change (10) DFS+Backtracking (10) Facebook Hacker Cup (10) Fast Slow Pointers (10) HackerRank Easy (10) Interval Tree (10) Limited Range (10) Matrix - Traverse (10) Monotone Queue (10) SPOJ (10) Starting Point (10) States (10) Stock (10) Theory (10) Tutorialhorizon (10) Kadane - Extended (9) Mathblog (9) Max-Min Flow (9) Maze (9) Median (9) O(32N) (9) Quick Select (9) Stack Overflow (9) System Design (9) Tree - Conversion (9) Use XOR (9) Book Notes (8) Company-Amazon (8) DFS+BFS (8) DP - States (8) Expression (8) Longest Common Subsequence(LCS) (8) One Pass (8) Quadtrees (8) Traversal Once (8) Trie - Suffix (8) 穷竭搜索 (8) Algorithm Problem List (7) All Sub (7) Catalan Number (7) Cycle (7) DP - Cases (7) Facebook Interview (7) Fibonacci Numbers (7) Flood fill (7) Game Nim (7) Graph BFS (7) HackerRank Difficult (7) Hackerearth (7) Inversion (7) Kadane’s Algorithm (7) Manacher (7) Morris Traversal (7) Multiple Data Structures (7) Normalized Key (7) O(XN) (7) Radix Sort (7) Recursion (7) Sampling (7) Suffix Array (7) Tech-Queries (7) Tree - Serialization (7) Tree DP (7) Trie - Bit (7) 蓝桥杯 (7) Algorithm - Brain Teaser (6) BFS - Priority Queue (6) BFS - Unusual (6) Classic Data Structure Impl (6) DP - 2D (6) DP - Monotone Queue (6) DP - Unusual (6) DP-Space Optimization (6) Dutch Flag (6) How To (6) Interviewstreet (6) Knapsack - MultiplePack (6) Local MinMax (6) MST (6) Minimum Spanning Tree (6) Number - Reach (6) Parentheses (6) Pre-Sum (6) Probability (6) Programming Pearls (6) Rabin-Karp (6) Reverse (6) Scan from right (6) Schedule (6) Stream (6) Subset Sum (6) TSP (6) Xpost (6) n00tc0d3r (6) reddit (6) AI (5) Abbreviation (5) Anagram (5) Art Of Programming-July (5) Assumption (5) Bellman Ford (5) Big Data (5) Code - Solid (5) Code Kata (5) Codility-lessons (5) Coding (5) Company - WMware (5) Convex Hull (5) Crazyforcode (5) DFS - Multiple (5) DFS+DP (5) DP - Multi-Dimension (5) DP-Multiple Relation (5) Eulerian Cycle (5) Graph - Unusual (5) Graph Cycle (5) Hash Strategy (5) Immutability (5) Java (5) LogN (5) Manhattan Distance (5) Matrix Chain Multiplication (5) N Queens (5) Pre-Sort: Index (5) Quick Partition (5) Quora (5) Randomized Algorithms (5) Resources (5) Robot (5) SPFA(Shortest Path Faster Algorithm) (5) Shuffle (5) Sieve of Eratosthenes (5) Strongly Connected Components (5) Subarray Sum (5) Sudoku (5) Suffix Tree (5) Swap (5) Threaded (5) Tree - Creation (5) Warshall Floyd (5) Word Search (5) jiuzhang (5)

    Popular Posts