391. 完美矩形
难度:困难
给你一个数组 rectangles ,其中 rectangles[i] = [xi, yi, ai, bi] 表示一个坐标轴平行的矩形。这个矩形的左下顶点是 (xi, yi) ,右上顶点是 (ai, bi) 。
如果所有矩形一起精确覆盖了某个矩形区域,则返回 true ;否则,返回 false 。
示例 1:
输入:rectangles = [[1,1,3,3],[3,1,4,2],[3,2,4,4],[1,3,2,4],[2,3,3,4]]
输出:true
解释:5 个矩形一起可以精确地覆盖一个矩形区域。
示例 2:
输入:rectangles = [[1,1,2,3],[1,3,2,4],[3,1,4,2],[3,2,4,4]]
输出:false
解释:两个矩形之间有间隔,无法覆盖成一个矩形。
示例 3:
输入:rectangles = [[1,1,3,3],[3,1,4,2],[1,3,2,4],[2,2,4,4]]
输出:false
解释:因为中间有相交区域,虽然形成了矩形,但不是精确覆盖。
分析:
这个问题有些难度,所以其标志为困难,通过率为46.1%。
看了这个题目,有几天没动手,但总在闲下来的时候,思考其处理。
首先我想到的是对给定的一系列矩形进行排序,然后按从左到右,从下到上的顺序依次拼接,看能不能拼接成一个完美矩形,或许这也是一种处理思路,但我还是没有付之行动,总觉得有些不太好处理。
后来我又想到一个方法,那就是既然给定的一系列矩形能够拼接成一个完美矩形,那么这些矩形的面积和一定等完美矩形的面积,如果相等就可以判定能够组成完美矩形,如果不相等,那就不能组成完美矩形。
正自以为得计,结果发现如果是上面的这个图形的话,虽说一系列矩形的面积和等于最大矩形面积,但中间有重叠的部分,并没有构成完美矩形,所以仅仅让矩形面积和等于最大矩形面积,还不能判断就能够组成完美矩形。
这让我联想到判断一个列表中有没有重复元素的方法,先将列表转换为集合,如果有重复就会自动去掉重复元素,这样元素个数就会减少,以元素个数是否减少来判断有没有重复元素,或许这里可以用到这种思想。
基于这种考虑,所以我又把每一个矩形分解为面积为1的小矩形,并用每一个小矩形的左下角坐标组成的元组,形成一个列表,是用左下角坐标组成元组而不是组成列表,是因为只有列表元素为不可变的对象才能进行这种转换,否则会出现“TypeError: unhashable type: 'list'”的错误提示。将所有矩形分解为这种小矩形并保存到一个列表中之后,然后转换为集合去重,再统计其元素个数,即可得到面积。如果这个面积与所有矩形面积之和相等,则说明没有重叠部分。
最后判断能不能构成完美矩形,只需要比较给定的一系列矩形组成的最大矩形区域面积,所有矩形面积和与去重之后的面积三者是否相等即可,如果三者相等,则能够构成完美矩形,否则不能构成完美矩形。
程序如下
#求一个矩形的面积
def s_rectangle(rectangle):
m=rectangle[2]-rectangle[0]
n=rectangle[3]-rectangle[1]
return m*n
#从给定的一系列矩形中返回最大面积的矩形区域
def max_rectangle(rectangles):
minx=min(list(map(lambda b:b[0],rectangles)))
miny=min(list(map(lambda b:b[1],rectangles)))
maxx=max(list(map(lambda b:b[2],rectangles)))
maxy=max(list(map(lambda b:b[3],rectangles)))
return [minx,miny,maxx,maxy]
#将一个矩形分解成面积为1的矩形集合,每个矩形仅用
#由左下角坐标形成的元组代表,返回左下角坐标的列表
def fj_rectangle(rectangle):
x1=rectangle[0]
x2=rectangle[2]
y1=rectangle[1]
y2=rectangle[3]
a=[(i,j) for i in range(x1,x2) for j in range(y1,y2)]
return a
#对给出的一系列矩形,计算每个矩形的面积并求和
#返回总面积和将所有矩形分解为面积为1的矩形的列表
def s(rectangles):
s1=0
b=[]
for i in rectangles:
s1=s1+s_rectangle(i)
b.extend(fj_rectangle(i))
return s1,b
def pd(rectangles):
#找出系列矩形的最大矩形区域并求出最大面积
rm=max_rectangle(rectangles)
sm=s_rectangle(rm)
#求出所有矩形的总面积和分解成面积为1的矩形列表
sf,a=s(rectangles)
#将矩形重叠的部分去掉之后求出其面积
b=len(set(a))
if sm==sf==b:
return True
else:
return False
rectangles=eval(input('pls input rectangles='))
print(pd(rectangles))
运行实例1:
pls input rectangles=[[1,1,3,3],[3,1,4,2],[3,2,4,4],[1,3,2,4],[2,3,3,4]]
True
运行实例2:
pls input rectangles=[[1,1,3,3],[3,1,4,2],[1,3,2,4],[2,2,4,4]]
False
感悟:
碰到困难,要迎难而上,多思考,多尝试。
要善于联想,多作知识的迁移,也只有多迁移,才能融会贯通,他山之石,可以攻玉。