Perfect Rectangle(完美矩形)

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

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

示例 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],
  [3,2,4,4]
]

返回 false。图形顶端留有间隔,无法覆盖成一个矩形。

示例 4:

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

返回 false。因为中间有相交区域,虽然形成了矩形,但不是精确覆盖。

这道题我在写前两个解法的时候还没ac通过,但是已经忍不住要写了。思路还是很清晰的,遍历矩形,算有没有重合,面积累加,最后看看总面积是不是最大范围的覆盖的矩形的面积。第一遍暴力解法:
class Solution {
public:
    bool Cover(vector<int>& a, vector<int>&b)
    {
        if (min(a[0], a[2]) >= max(b[0], b[2]) || max(a[0], a[2]) <= min(b[0], b[2])
            || min(a[1], a[3]) >= max(b[1], b[3]) || max(a[1], a[3]) <= min(b[1], b[3]))
        {
            return false;
        }
        return true;
    }
    bool isRectangleCover(vector<vector<int>>& rectangles) {
        int minx, miny, maxx, maxy;
        minx = miny = INT_MAX;
        maxx = maxy = INT_MIN;
        long long int sum = 0;
        for (int i = 0; i < rectangles.size();i++)
        {
            for (int r = 0; r < i;r++)
            {
                if (Cover(rectangles[i], rectangles[r]))
                {
                    return false;
                }
            }
            minx = min(minx, min(rectangles[i][0], rectangles[i][2]));
            miny = min(miny, min(rectangles[i][1], rectangles[i][3]));
            maxx = max(maxx, max(rectangles[i][0], rectangles[i][2]));
            maxy = max(maxy, max(rectangles[i][1], rectangles[i][3]));
            sum += abs((rectangles[i][0] - rectangles[i][2])*(rectangles[i][1] - rectangles[i][3]));
        }
        return sum == (maxx - minx)*(maxy - miny);
    }
};

果不其然挂了,测试最后两组都是3w+的数据量

第二遍:四叉树解法

class QuadNode
{
public:
    enum{
        quad_1,//四个象限
        quad_2,
        quad_3,
        quad_4,
        quad_count,
    };
    vector<vector<int>>* data;
    QuadNode* Children[quad_count];//孩子指针,数组大小为8
    QuadNode* Parent;//父节点指针
    typedef std::list<int> RecList;
    typedef std::list<int>::iterator RecListIter;
    RecList rectlist;//携带的参数  实体列表
    int quad;//在父节点中的象限
    int deep;//自己所在的层索引
    int minx,miny;
    int maxx,maxy;
    QuadNode(vector<vector<int>>* data, int x1, int x2, int y1, int y2, int dp, int qd)
    {
        minx = x1;
        maxx = x2;
        miny = y1;
        maxy = y2;
        deep = dp;
        quad = qd;
        Parent = NULL;
        this->data = data;
        memset(Children, 0, sizeof(Children));
    }
    ~QuadNode()
    {
        for (int i = 0; i < quad_count; i++)
        {
            if (Children[i])
            {
                delete Children[i];
                Children[i] = NULL;
            }
        }
        rectlist.clear();
    }
    QuadNode* GetDeepest(int index)
    {
        if (deep > 0)
        {
            //4个孩子都要创建
            for (int r = 0; r < QuadNode::quad_count; r++)
            {
                if (!Children[r])
                {
                    int ix = r == QuadNode::quad_1 || r == QuadNode::quad_3 ? minx : (minx + maxx) / 2;
                    int ax = r == QuadNode::quad_1 || r == QuadNode::quad_3 ? (minx + maxx) / 2 : maxx;

                    int iy = r == QuadNode::quad_1 || r == QuadNode::quad_2 ? miny : (miny + maxy) / 2;
                    int ay = r == QuadNode::quad_1 || r == QuadNode::quad_2 ? (miny + maxy) / 2 : maxy;
                    QuadNode *node = new QuadNode(data, ix, ax, iy, ay, deep - 1, r);
                    node->Parent = this;
                    Children[r] = node;
                }
                if (Children[r]->CheckInRange(index))
                {
                    return Children[r]->GetDeepest(index);
                }
            }
        }
        return this;
    }
    bool CheckInRange(int index)
    {
        if ((*data)[index][0] >= minx && (*data)[index][2] <= maxx && (*data)[index][1] >= miny && (*data)[index][3] <= maxy)
        {
            return true;
        }
        return false;
    }
    bool CheckCover(int index)
    {
        QuadNode* n = GetDeepest(index);
        QuadNode* parent = n->Parent;
        while (parent)
        {
            if (parent->CheckWithTrianglelist(index))
            {
                return true;
            }
            parent = parent->Parent;
        }

        if (n->CollisionCheck(index))
            return true;
        n->rectlist.push_back(index);
        return false;
    }
    bool CollisionCheck(int index)
    {
        return CheckWithTrianglelist(index) || CheckWithSubSpace(index);
    }
    bool CheckWithTrianglelist(int index)
    {
        RecListIter itr = rectlist.begin();
        while (itr != rectlist.end())
        {
            int id = *itr;
            if (Cover((*data)[id], (*data)[index]))
            {
                return true;
            }
            itr++;
        }
        return false;
    }

    bool CheckWithSubSpace(int index)
    {
        bool collision = false;
        for (int i = 0; i < quad_count && Children[i]; i++)
        {
            int vec[] = { minx, miny, maxx, maxy };
            vector<int> para(vec, vec + 4);
            if (Cover((*data)[index], para))
            {
                collision |= Children[i]->CollisionCheck(index);
            }
            if (collision)
            {
                return true;
            }
        }
        return false;
    }

    bool Cover(vector<int>& a, vector<int>&b)
    {
        if (min(a[0], a[2]) >= max(b[0], b[2]) || max(a[0], a[2]) <= min(b[0], b[2])
            || min(a[1], a[3]) >= max(b[1], b[3]) || max(a[1], a[3]) <= min(b[1], b[3]))
        {
            return false;
        }
        return true;
    }
};
class Solution {
public:
    int GetMax2Power(int xmax, int ymax, int& lg)
    {
        int max = xmax;
        if (ymax > max)
            max = ymax;
        if ((max & (max - 1)) == 0)
        {
            double L = log(max*1.0) / log(2.0);
            lg = (int)L + 1;
            return max;
        }
        else
        {
            double L = log(max*1.0) / log(2.0);
            lg = (int)L + 2;
            return (int)pow(2 * 1.0, lg - 1.0);
        }
    }
    bool isRectangleCover(vector<vector<int>>& rectangles) {
        int minx, miny, maxx, maxy;
        minx = miny = INT_MAX;
        maxx = maxy = INT_MIN;
        long long int sum = 0;
        for (int i = 0; i < rectangles.size(); i++)
        {
            minx = min(minx, min(rectangles[i][0], rectangles[i][2]));
            miny = min(miny, min(rectangles[i][1], rectangles[i][3]));
            maxx = max(maxx, max(rectangles[i][0], rectangles[i][2]));
            maxy = max(maxy, max(rectangles[i][1], rectangles[i][3]));
        }
        int mx = max(abs(maxx), abs(minx));
        int my = max(abs(maxy), abs(miny));
        int range, lg;
        range = GetMax2Power(mx, my, lg);
        //四叉树
        QuadNode* root = new QuadNode(&rectangles, -range, range, -range, range, lg, 0);

        for (int i = 0; i < rectangles.size();i++)
        {
            if (root->CheckCover(i))
            {
                return false;
            }
            sum += abs((rectangles[i][0] - rectangles[i][2])*(rectangles[i][1] - rectangles[i][3]));
        }
        delete root;
        return sum == (maxx - minx)*(maxy - miny);
    }
};

以为没什么问题了,跑一下又超时了,真是恶心的一p啊。拿测试数据跑一跑发现,几乎95%的数据都在边界上,四叉树无法往下细化。写个四叉树容易吗???

只能硬着头皮继续想了,果然没有想到。参考了下别人的歪门邪道,感觉前面写的东西都白瞎了。有时候解决问题,还得靠技巧。

解法三:所有的矩形顶点,有且只有四个边角是只出现一次,剩下的顶点要么两次,要么四次

   long long int getHash(int x, int y)
    {
        long long int t = 2 << 16;
        return x*t + y;
    }
    bool isRectangleCover(vector<vector<int>>& rectangles) {
        int minx, miny, maxx, maxy;
        minx = miny = INT_MAX;
        maxx = maxy = INT_MIN;
        long long int sum = 0;
        unordered_set<long long int> st;
        for (int i = 0; i < rectangles.size(); i++)
        {
            minx = min(minx, min(rectangles[i][0], rectangles[i][2]));
            miny = min(miny, min(rectangles[i][1], rectangles[i][3]));
            maxx = max(maxx, max(rectangles[i][0], rectangles[i][2]));
            maxy = max(maxy, max(rectangles[i][1], rectangles[i][3]));
            sum += abs((rectangles[i][0] - rectangles[i][2])*(rectangles[i][1] - rectangles[i][3]));
            long long int lu = getHash(rectangles[i][0], rectangles[i][3]);
            long long int ld = getHash(rectangles[i][0], rectangles[i][1]);
            long long int ru = getHash(rectangles[i][2], rectangles[i][3]);
            long long int rd = getHash(rectangles[i][2], rectangles[i][1]);
            if (st.count(lu) == 0) st.insert(lu);
            else st.erase(lu);
            if (st.count(ld) == 0) st.insert(ld);
            else st.erase(ld);
            if (st.count(ru) == 0) st.insert(ru);
            else st.erase(ru);
            if (st.count(rd) == 0) st.insert(rd);
            else st.erase(rd);
        }

        return sum == (maxx - minx)*(maxy - miny) && st.size() == 4
            && st.count(getHash(minx, miny)) == 1
            && st.count(getHash(minx, maxy)) == 1
            && st.count(getHash(maxx, miny)) == 1
            && st.count(getHash(maxx, maxy)) == 1;
    }

吐血!

原文地址:https://www.cnblogs.com/shit/p/9726245.html

时间: 2024-10-16 12:59:16

Perfect Rectangle(完美矩形)的相关文章

391 Perfect Rectangle 完美矩形

有 N 个与坐标轴对齐的矩形, 其中 N > 0, 判断它们是否能精确地覆盖一个矩形区域.每个矩形用左下角的点和右上角的点的坐标来表示.例如, 一个单位正方形可以表示为 [1,1,2,2]. ( 左下角的点的坐标为 (1, 1) 以及右上角的点的坐标为 (2, 2) ). 详见:https://leetcode.com/problems/perfect-rectangle/description/ C++: class Solution { public: bool isRectangleCov

[Swift]LeetCode391. 完美矩形 | 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

391. 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

LeetCode:Rectangle Area - 矩形交叉部分的面积

1.题目名称 Rectangle Area(矩形交叉部分的面积) 2.题目地址 https://leetcode.com/problems/rectangle-area/ 3.题目内容 英文:Find the total area covered by two rectilinear rectangles in a 2D plane. Each rectangle is defined by its bottom left corner and top right corner as shown

[LeetCode] Perfect Number 完美数字

We define the Perfect Number is a positive integer that is equal to the sum of all its positive divisors except itself. Now, given an integer n, write a function that returns true when it is a perfect number and false when it is not. Example: Input:

[LeetCode] Maximal Rectangle 最大矩形

Given a 2D binary matrix filled with 0's and 1's, find the largest rectangle containing all ones and return its area. 此题是之前那道的Largest Rectangle in Histogram 直方图中最大的矩形 的扩展,这道题的二维矩阵每一层向上都可以看做一个直方图,输入矩阵有多少行,就可以形成多少个直方图,对每个直方图都调用Largest Rectangle in Hist

Leetcode: 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

设计并测试一个名为Rectangle的矩形类

//其属性为矩形的左下角和右上角两个点的坐标,能计算矩形的面积. #include <iostream> using namespace std; class Rectangle { public : Rectangle() {}; Rectangle(int iLeftX,int iLeftY,int iRightX,int iRightY) { this->iLeftX=iLeftX; this->iLeftY=iLeftY; this->iRightX=iRightX;

[LeetCode] Rectangle Area 矩形面积

Find the total area covered by two rectilinear rectangles in a2D plane. Each rectangle is defined by its bottom left corner and top right corner as shown in the figure. Assume that the total area is never beyond the maximum possible value of int. Cre