1. 程式人生 > >【LeetCode】963. Minimum Area Rectangle II 解題報告(Python)

【LeetCode】963. Minimum Area Rectangle II 解題報告(Python)

作者: 負雪明燭
id: fuxuemingzhu
個人部落格: http://fuxuemingzhu.cn/


目錄

題目地址: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 <= pointsi <= 40000
  4. All points are distinct.
  5. Answers within 10^-5 of the actual value will be accepted as correct.

題目大意

給定一組座標,找出四個頂點使其能構成長方形,求最小的長方形的面積。注意,邊有可能不和x,y軸平行。

解題方法

線段長+線段中心+字典

前面有個平行於座標軸的長方形題目,那個題目是固定對角線的兩個點就能找出剩餘兩個點了,但是這個題可以不和座標軸平行,那麼問題就變大了。。

想來想去還是用長方形的性質,不過很顯然仍然是和物件線有關的性質:

  1. 長方形的兩條對角線長度相等;
  2. 長方形的兩條對角線互相平分(中點重合);

注意,如果滿足上面兩個條件的四邊形就是長方形。

用上了這兩個性質之後,題目從的處理直接變成了線段的處理,時間複雜度降到了O(N^2).

具體做法是,我們求出任意兩個點構成的線段的長度(的平方)、線段的中心座標,然後用字典儲存成(長度,中心點x,中心點y):[(線段1起點,線段1終點), (線段2起點,線段2終點)……]。把這個字典弄好了之後,我們需要對字典做一次遍歷,依次遍歷相同長度和中心點的兩個線段構成的長方形的面積,保留最小值就好了。

知道兩條對角線座標,求長方形的面積,方法是找兩條臨邊,然後相乘即可。

python程式碼如下:

class Solution(object):
    def minAreaFreeRect(self, points):
        """
        :type points: List[List[int]]
        :rtype: float
        """
        N = len(points)
        # (l^2, x#, y#) : [(0,1), (1,2)]
        d = collections.defaultdict(list)
        for i in range(N - 1):
            pi = points[i]
            for j in range(i + 1, N):
                pj = points[j]
                l = (pi[0] - pj[0]) ** 2 + (pi[1] - pj[1]) ** 2
                x = (pi[0] + pj[0]) / 2.0
                y = (pi[1] + pj[1]) / 2.0
                d[(l, x, y)].append((i, j))
        res = float("inf")
        for l in d.values():
            M = len(l)
            for i in range(M - 1):
                p0, p2 = points[l[i][0]], points[l[i][1]]
                for j in range(i + 1, M):
                    p1, p3 = points[l[j][0]], points[l[j][1]]
                    d1 = math.sqrt((p0[0] - p1[0]) ** 2 + (p0[1] - p1[1]) ** 2)
                    d2 = math.sqrt((p1[0] - p2[0]) ** 2 + (p1[1] - p2[1]) ** 2)
                    area = d1 * d2
                    res = min(res, area)
        return 0 if res == float('inf') else res

日期

2018 年 12 月 23 日 —— 周賽成績新高