[leetcode] 391. Perfect Rectangle 解题报告

题目链接:https://leetcode.com/problems/perfect-rectangle/

Given N axis-aligned rectangles where N > 0, determine if they all together form an exact cover of a rectangular region.

Each rectangle is represented as a bottom-left point and a top-right point. For example, a unit square is represented as [1,1,2,2]. (coordinate of bottom-left point is (1, 1) and top-right point is (2, 2)).

Example 1:

rectangles = [
  [1,1,3,3],
  [3,1,4,2],
  [3,2,4,4],
  [1,3,2,4],
  [2,3,3,4]
]

Return true. All 5 rectangles together form an exact cover of a rectangular region.

Example 2:

rectangles = [
  [1,1,2,3],
  [1,3,2,4],
  [3,1,4,2],
  [3,2,4,4]
]

Return false. Because there is a gap between the two rectangular regions.

Example 3:

rectangles = [
  [1,1,3,3],
  [3,1,4,2],
  [1,3,2,4],
  [3,2,4,4]
]

Return false. Because there is a gap in the top center.

Example 4:

rectangles = [
  [1,1,3,3],
  [3,1,4,2],
  [1,3,2,4],
  [2,2,4,4]
]

Return false. Because two of the rectangles overlap with each other

思路:一种naive的做法是先计算总共小矩阵的面积和四个边界的面积,如果不相等则返回false.否则就要计算是否有重叠,计算重叠的方式是两两检查即可.这样时间复杂度是O(n^2),并不能过掉所有数据.所以我们需要一种更聪明的做法.

如果一堆小矩形要组成一个完美的大矩形需要满足以下条件:

[leetcode] 391. Perfect Rectangle 解题报告_第1张图片

1.蓝色的点一个位置只能出现一次,并且只有四个这样的点

2.绿色的点一个位置只能出现两次

3.红色的点一个位置只能出现四次

也就是只能存在以上类型的点,并且我们给一个矩形的四个角编号分别为1,2,3,4,那么出现在同一个位置的点必须为一个矩阵不同编号的点.如此条件都满足即可构成一个完美矩形.

算法实现步骤如下:

1.先遍历每一个矩阵,对每一个点进行处理,对于每一个位置的点用hash表来存储这个位置出现了几个corner,并且为了区分出现在这个位置的点是什么编号,我们可以用一个掩码来表示这个点的编号,这样也好判断是否这个位置出现了重复的编号的corner.

2. 对矩阵做好处理之后接下来就好遍历hash表查看对于每个位置来说是否满足以上规定的点的形式.任意一个点不满足条件即可返回false.

在实现的过程中为了简化代码用了一些技巧,比如为了在hash表中保存一个坐标,可以用字符串形式来保存.还有判断一个数是否是2的倍数可以用val&(-val)是否为0来判断.

这样时间复杂度即可降为O(n)

代码如下:

class Solution {
public:
    bool isRectangleCover(vector>& rectangles) {
        unordered_map hash;
        for(auto val: rectangles)
        {
            for(int i = 0; i < 4; i++)
            {
                string tem = to_string(val[i/2*2])+','+to_string(val[i%2*2+1]);
                if(hash[tem]&(1< 4) return false;
            if((sec&(sec-1)) && !(sec==3||sec==12||sec==5||sec==10||sec==15)) 
                return false;
        }
        return true;
    }
};


参考:https://discuss.leetcode.com/topic/56677/concise-15-lines-o-n-c-solution

https://discuss.leetcode.com/topic/55923/o-n-solution-by-counting-corners-with-detailed-explaination







你可能感兴趣的:(leetcode,hash,math)