每日一题 0126


(2022.01.26)每日一题 检测正方形

芜湖,中等题,第一想法,算出所有的点,遍历查找,属实脑子不对劲。然后想到使用哈希表,存储所有的点出现及其出现的次数。

因为已知了一个查询点,那么轴对齐正方形的各个顶点就会非常好算。当查询点\((x,y)\)存在轴对齐正方形时,必然在点集中存在与其 \(x\) 值或 \(y\) 值相同的点,即与查询点构成的直线平行于 \(x\) 轴或 \(y\) 轴。所以我们使用unorderd_map构建哈希表,记录点出现的次数。我们以 \(y\) 值相同,\(x\) 值不同来找第一个点,当我们找到该点时,我们可以计算出正方形的剩余两个点,我们只要去判断这两个点是否存在于哈希表中,并计算次数即可。

为了方便表示,我们设查询点\(X=(x,y)\),参照点\(Y=(x1,y)\),那么剩下的两个点的坐标分别是\(((x,y+abs(x-x1)),(x1,y+abs(x-x1))\)\((x,y-abs(x-x1)),(x1,y-abs(x-x1)))\)。最后计算对应两点的个数相乘后相加即可,当然还要乘以我们参照点的个数。最后需要注意的是一定要将与我们查询点相同的点筛出,我就是一开始忘记筛出了,就会出错,这样按照代码的逻辑也是可以计算的,就是计算与查询点相同的点的个数相乘,相加,再乘以参照点的个数。总而言之就是很弱智的错误,用于提醒一下自己。

class DetectSquares {
public:
    unordered_map> cnt;
    DetectSquares() {

    }
    
    void add(vector point) {
        int x = point[0], y = point[1];
        cnt[y][x]++;
    }
    
    int count(vector point) {
        int x = point[0];
        int y = point[1];
        int res = 0;
        if(!cnt.count(y)){
            return 0;
        }
        for(auto& tmp: cnt[y]){
            int tmp_x = tmp.first;
            if(tmp_x == x) continue;
            // int edge = (x - tmp_x)>0?(x-tmp_x):(tmp_x - x);
            // int edge = abs(x-tmp_x);
            int p1_x = x;
            int p1_y = y - edge;
            int p2_x = x;
            int p2_y = y + edge;
            int p3_x = tmp_x;
            int p3_y = y - edge;
            int p4_x = tmp_x;
            int p4_y = y + edge;
            res+= tmp.second*(cnt[p1_y][p1_x]*cnt[p3_y][p3_x] + cnt[p2_y][p2_x]*cnt[p4_y][p4_x]);
        }
        return res;
    }
};
/**
 * Your DetectSquares object will be instantiated and called as such:
 * DetectSquares* obj = new DetectSquares();
 * obj->add(point);
 * int param_2 = obj->count(point);
 */