LeetCode 完美矩形

我们有 N 个与坐标轴对齐的矩形, 其中 N > 0, 判断它们是否能精确地覆盖一个矩形区域。

每个矩形用左下角的点和右上角的点的坐标来表示。例如, 一个单位正方形可以表示为 [1,1,2,2]。 ( 左下角的点的坐标为 (1, 1) 以及右上角的点的坐标为 (2, 2) )。
LeetCode 完美矩形_第1张图片
示例 1:

rectangles = [
  [1,1,3,3],
  [3,1,4,2],
  [3,2,4,4],
  [1,3,2,4],
  [2,3,3,4]
]
返回 true。5个矩形一起可以精确地覆盖一个矩形区域。

LeetCode 完美矩形_第2张图片

示例 2:

rectangles = [
  [1,1,2,3],
  [1,3,2,4],
  [3,1,4,2],
  [3,2,4,4]
]
返回 false。两个矩形之间有间隔,无法覆盖成一个矩形。

LeetCode 完美矩形_第3张图片
示例 3:

rectangles = [
  [1,1,3,3],
  [3,1,4,2],
  [1,3,2,4],
  [3,2,4,4]
]
返回 false。图形顶端留有间隔,无法覆盖成一个矩形。

LeetCode 完美矩形_第4张图片
示例 4:

rectangles = [
  [1,1,3,3],
  [3,1,4,2],
  [1,3,2,4],
  [2,2,4,4]
]
返回 false。因为中间有相交区域,虽然形成了矩形,但不是精确覆盖。

思路分析:如果所有小矩形能够拼凑成大矩形,那么所有小矩形的面积和必定和大矩形的面积相等,且大矩形被小矩形完全覆盖。
方法一:蛮力法。

class Solution {
public:
    bool isRectangleCover(vector>& rectangles) {
        long long area = 0;//所有小矩形的总面积
        int leftDownRow = INT_MAX / 2, leftDownCol = INT_MAX / 2;//大矩形左下角
        int rightUpRow = INT_MIN / 2, rightUpCol = INT_MIN / 2;//大矩形右上角
        //遍历所有小矩形
        for (auto &rectangle : rectangles){
            area = area + (long long)(rectangle[2] - rectangle[0]) * (long long)(rectangle[3] - rectangle[1]);//小矩形面积
            //寻找大矩形的可能最左下角的下标
            if (leftDownRow + leftDownCol > rectangle[0] + rectangle[1]){
                leftDownRow = rectangle[0];
                leftDownCol = rectangle[1];
            }
            //寻找大矩形的可能最有上角的下标
            if (rightUpRow + rightUpCol < rectangle[2] + rectangle[3]){
                rightUpRow = rectangle[2];
                rightUpCol = rectangle[3];
            }
        }
        //如果所有小矩形的面积和和可能的最大矩形面积不相等,说明不能构成大矩形
        if ((long long)(rightUpRow - leftDownRow) * (long long)(rightUpCol - leftDownCol) != area){
            return false;
        }
        //将大矩形所有节点标记
        map, bool> myMap;
        for (int row = leftDownRow; row < rightUpRow; ++row){
            for (int col = leftDownCol; col < rightUpCol; ++col){
                myMap[make_pair(row, col)] = false;
            }
        }
        //遍历所有小矩形
        for (auto &rectangle : rectangles){
            for (int row = rectangle[0]; row < rectangle[2]; ++row){
                for (int col = rectangle[1]; col < rectangle[3]; ++col){
                //如果这个点不在大矩形返回,或者之前就被标记了(重叠)
                    if (myMap.count(make_pair(row, col)) == 0 || myMap[make_pair(row, col)]){
                        return false;
                    }
                    else{
                        myMap[make_pair(row, col)] = true;//否则标记
                    }
                }
            }
        }
        return true;
    }
};

LeetCode 完美矩形_第5张图片
方法二:并不将所有大矩形中的点进行标记,而是从放入的小矩形入手,将矩形两点表示修改为四点表示。每次访问一个小矩形都尝试将其四个顶点放入set,如果某个点之前set就存在,那么移除,否则放入集合。如果是完美矩形,那么最后set剩余的必定是大矩形的四个角。因为如果是完美矩形,其他点必定出现偶数次。

class Solution {
public:
    bool isRectangleCover(vector>& rectangles) {
        long long area = 0;//所有小矩形的总面积
        int leftDownRow = INT_MAX / 2, leftDownCol = INT_MAX / 2;//大矩形左下角
        int rightUpRow = INT_MIN / 2, rightUpCol = INT_MIN / 2;//大矩形右上角
        set> mySet;//标记点
        //遍历所有小矩形
        for (auto &rectangle : rectangles){
            area = area + (long long)(rectangle[2] - rectangle[0]) * (long long)(rectangle[3] - rectangle[1]);//小矩形面积
            //寻找大矩形的可能最左下角的下标
            leftDownRow = min(leftDownRow, rectangle[0]);
            leftDownCol = min(leftDownCol, rectangle[1]);
            //寻找大矩形的可能最有上角的下标
            rightUpRow = max(rightUpRow, rectangle[2]);
            rightUpCol = max(rightUpCol, rectangle[3]);
            //将四个点进行确认
            //左下角
            if (mySet.find({rectangle[0], rectangle[1]}) == mySet.end()){
                mySet.insert({rectangle[0], rectangle[1]});
            }
            else{
                mySet.erase({rectangle[0], rectangle[1]});
            }
            //右上角
            if (mySet.find({rectangle[2], rectangle[3]}) == mySet.end()){
                mySet.insert({rectangle[2], rectangle[3]});
            }
            else{
                mySet.erase({rectangle[2], rectangle[3]});
            }
            //左上角
            if (mySet.find({rectangle[0], rectangle[3]}) == mySet.end()){
                mySet.insert({rectangle[0], rectangle[3]});
            }
            else{
                mySet.erase({rectangle[0], rectangle[3]});
            }
            //右下角
            if (mySet.find({rectangle[2], rectangle[1]}) == mySet.end()){
                mySet.insert({rectangle[2], rectangle[1]});
            }
            else{
                mySet.erase({rectangle[2], rectangle[1]});
            }
        }
        //如果是完美矩形,最后必定只剩四个点
        if (mySet.size() == 4 && mySet.find({leftDownRow, leftDownCol}) != mySet.end() && mySet.find({rightUpRow, rightUpCol}) != mySet.end() && mySet.find({leftDownRow, rightUpCol}) != mySet.end() && mySet.find({rightUpRow, leftDownCol}) != mySet.end()){
            //如果所有小矩形的面积和和可能的最大矩形面积相等,说明能构成大矩形
            if ((long long)(rightUpRow - leftDownRow) * (long long)(rightUpCol - leftDownCol) == area){
                return true;
            }
        }
        return false;
    }
};

LeetCode 完美矩形_第6张图片

你可能感兴趣的:(LeetCode)