自己编写的leetcode题目

题目

给你一组二维的cv::Point2d点,这些点都是平均分布在图像中,图像中还有一些二维边界框cv::Rect,如何快速判断这些点是否在这些边界框内,要求输入的数据有两组,一组是在边界框内的点,一组是不在边界框内的点,要求实现时间复杂度为O(n)

解析

要在O(n)时间内快速判断一组点是否在一组边界框内,你可以使用空间分割树(Spatial Partition Tree)或类似的数据结构来优化这个问题。以下是一种解决方案:

  1. 创建一个空间分割树(如四叉树),将图像分割成多个子区域。这些子区域可以根据需要进一步细分,直到达到适当的深度。

  2. 遍历所有的边界框,将每个边界框与空间分割树进行相交测试,将边界框放入与其相交的子区域中。这可以通过比较边界框的位置与子区域的位置来实现。

  3. 然后,遍历你的点集。对于每个点,你可以快速确定它属于哪个子区域,因为每个点都只需要与空间分割树的一部分进行比较。如果一个点位于某个边界框内,它一定位于该边界框所在的子区域内。这使你能够快速定位到可能包含该点的边界框。

  4. 最后,对于每个点,只需要对其所在的子区域内的边界框进行测试,以确定它是否在边界框内。这将大大减少必须测试的边界框数量,从而实现O(n)的时间复杂度。

这个算法的关键在于使用空间分割树来减少测试的数量,从而提高了查找的效率。在实际实现时,你需要考虑如何构建和维护这个树以及如何实现与边界框的相交测试。但这个方法将帮助你在O(n)的时间内快速判断一组点是否在一组边界框内。

代码

#include <iostream>
#include <vector>
#include <opencv2/opencv.hpp>

using namespace std;
using namespace cv;

// 定义空间分割树节点
struct QuadTreeNode {
    
    
    Rect boundary; // 区域的边界框
    vector<Point2d> points; // 区域内的点
    QuadTreeNode* children[4]; // 四个象限的子节点

    QuadTreeNode(const Rect& rect) : boundary(rect) {
    
    
        for (int i = 0; i < 4; i++) {
    
    
            children[i] = nullptr;
        }
    }

    // 插入一个点
    void insert(const Point2d& point) {
    
    
        // 如果该节点没有子节点,直接插入点
        if (children[0] == nullptr) {
    
    
            points.push_back(point);
            return;
        }

        // 否则,根据点的位置将点插入子节点中
        for (int i = 0; i < 4; i++) {
    
    
            if (children[i]->boundary.contains(point)) {
    
    
                children[i]->insert(point);
                return;
            }
        }
    }
};

// 判断点是否在边界框内
bool isPointInRect(const Point2d& point, const Rect& boundary) {
    
    
    return (point.x >= boundary.x && point.x <= boundary.x + boundary.width &&
            point.y >= boundary.y && point.y <= boundary.y + boundary.height);
}

// 快速检查一组点是否在一组边界框内
void checkPointsInRectangles(const vector<Point2d>& points, const vector<Rect>& rectangles) {
    
    
    QuadTreeNode* root = new QuadTreeNode(Rect(Point(0, 0), Point(100, 100))); // 假设整个图像大小为100x100

    // 插入边界框内的点
    for (const Rect& rect : rectangles) {
    
    
        for (const Point2d& point : points) {
    
    
            if (rect.contains(point)) {
    
    
                root->insert(point);
            }
        }
    }

    // 遍历所有的点并检查是否在边界框内
    for (const Point2d& point : points) {
    
    
        bool isInside = false;

        // 如果点在根节点内,则进一步检查
        if (root->boundary.contains(point)) {
    
    
            for (int i = 0; i < 4; i++) {
    
    
                if (root->children[i] != nullptr) {
    
    
                    // 检查点是否在子节点内
                    if (isPointInRect(point, root->children[i]->boundary)) {
    
    
                        for (const Point2d& p : root->children[i]->points) {
    
    
                            if (p == point) {
    
    
                                isInside = true;
                                break;
                            }
                        }
                    }
                    if (isInside) break;
                }
            }
        }

        if (isInside) {
    
    
            cout << "Point (" << point.x << ", " << point.y << ") is inside a rectangle." << endl;
        } else {
    
    
            cout << "Point (" << point.x << ", " << point.y << ") is not inside any rectangle." << endl;
        }
    }
}

int main() {
    
    
    vector<Point2d> pointsInRect; // 存放在边界框内的点
    vector<Point2d> pointsOutsideRect; // 存放不在边界框内的点

    // 填充点集合(示例)
    pointsInRect.push_back(Point2d(30, 30));
    pointsInRect.push_back(Point2d(10, 10));
    pointsOutsideRect.push_back(Point2d(80, 80));
    pointsOutsideRect.push_back(Point2d(5, 90));

    vector<Rect> rectangles; // 存放边界框

    // 填充边界框集合(示例)
    rectangles.push_back(Rect(20, 20, 20, 20));
    rectangles.push_back(Rect(5, 5, 10, 10));

    // 检查点是否在边界框内
    checkPointsInRectangles(pointsInRect, rectangles);
    checkPointsInRectangles(pointsOutsideRect, rectangles);

    return 0;
}

猜你喜欢

转载自blog.csdn.net/CCCrunner/article/details/134011822
今日推荐