• 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;
        }

    吐血!

  • 相关阅读:
    boost常用记录
    redis系列-redis的持久化
    分布式存储的一些概念
    搜索引擎学习-实现
    搜索引擎学习-概述
    设计模式-创建型模式(读书笔记)
    redis系列-redis的使用场景
    分布式系统设计准则
    2018/12/06 eclipse 快速加载需要的包
    2018/12/06 L1-028 判断素数 Java
  • 原文地址:https://www.cnblogs.com/shit/p/9726245.html
Copyright © 2020-2023  润新知