【LeetCode】939. Minimum Area Rectangle 解題報告(Python)
作者: 負雪明燭
id: fuxuemingzhu
個人部落格: http://fuxuemingzhu.cn/
目錄
題目地址:https://leetcode.com/problems/minimum-area-rectangle/description/
題目描述
Given a set of points in the xy-plane, determine the minimum area of a rectangle formed from these points, with sides parallel to the x
y
axes.
If there isn’t any rectangle, return 0.
Example 1:
Input: [[1,1],[1,3],[3,1],[3,3],[2,2]]
Output: 4
Example 2:
Input: [[1,1],[1,3],[3,1],[3,3],[4,1],[4,3]]
Output: 2
Note:
1 <= points.length <= 500
0 <= points[i][0] <= 40000
0 <= points[i][1] <= 40000
- All points are distinct.
題目大意
給了很多點,找出這些點中,任意選擇4個點,形成一個長方形,要求長方形的邊必須平行與座標軸。求最小面積的長方形的面積是多少。
解題方法
確定對角線,找另外兩點(4sum)
周賽的第三題,超時了很多次,確實需要優秀的解法才能通過。
最原始的想法就是,我們找出和座標軸平行的三個點,來確定第四個點。這麼做的話,時間複雜度是O(N^3),果然超時了。這說明我對4sum理解還不夠深刻啊!兩天前剛做過的454. 4Sum II,做法就是確定兩個數字的和,然後看剩餘的兩個數字的和是否存在即可。也就是說4sum的時間複雜度只有O(N^2)。
這個題正確的做法是先確定對角線兩個點!題目要求所有的邊必須平行座標軸,就是告訴我們只用確定對角線兩個元素,剩餘的兩個點可以直接求出來即可!因此不需要確定3個點的O(N^3)的遍歷。
所以啊,還是需要活學活用才行啊!
時間複雜度是O(N^2),空間複雜度是O(N)。
class Solution(object):
def minAreaRect(self, points):
"""
:type points: List[List[int]]
:rtype: int
"""
points = map(tuple, points)
points.sort()
pset = set(points)
N = len(points)
res = float('inf')
for i in range(N - 1):
p1 = points[i]
for j in range(i + 1, N):
p4 = points[j]
if p4[0] == p1[0] or p4[1] == p1[1]:
continue
p2 = (p1[0], p4[1])
p3 = (p4[0], p1[1])
if p2 in pset and p3 in pset:
res = min(res, abs(p3[0] - p1[0]) * abs(p2[1] - p1[1]))
return res if res != float("inf") else 0
字典儲存出現的x值,y值的點
另一個高效的演算法是使用字典進行儲存。這樣的話,如果我們確定了一個點(x,y),那麼可以快速找到和它相同x座標或者y座標的所有點,然後只用遍歷這些點就行了。
具體做法是,使用兩個字典xdict和ydict,儲存每個x,y對應的座標。然後對相同的x進行O(N^2)的遍歷。這時相當於確定了相同x的兩個點,然後對相同的y再進行遍歷,這樣確定了第三個點。第四個點不用遍歷,可以直接查詢是不是在所有的點中出現了即可。
最壞時間複雜度是O(N^3),空間複雜度是O(N)。
class Solution(object):
def minAreaRect(self, points):
"""
:type points: List[List[int]]
:rtype: int
"""
points = map(tuple, points)
points.sort()
xdict, ydict = collections.defaultdict(list), collections.defaultdict(list)
pset = set()
res = float("inf")
for point in points:
xdict[point[0]].append(point)
ydict[point[1]].append(point)
pset.add(point)
for x1 in xdict.keys():
if len(xdict[x1]) == 1:
continue
for i in range(len(xdict[x1]) - 1):
p1 = xdict[x1][i]
for j in range(i + 1, len(xdict[x1])):
p2 = xdict[x1][j]
for p3 in ydict[p1[1]]:
if p3 != p1:
if (p3[0], p2[1]) in pset:
res = min(res, abs((p3[0] - p1[0]) * (p2[1] - p1[1])))
return res if res != float("inf") else 0
日期
2018 年 11 月 11 日 —— 剁手節快樂