leetcode每日一题-检测正方形
这篇题解给出了 LeetCode Detect Squares 的哈希建模方案,核心是“按行组织点、按列枚举边”。建模方式使用 unordered_map<y, unordered_map<x, cnt>> 记录二维点及其出现次数。相比简单 pair-key 写法,这种结构更方便按行/按列做局部检索。同时天然支持重复点…
题目 题目链接 题目解析 注意此题为计算几何类型的题目,我认为这类问题最重要的就是把这个几何图形用好用的方法去表示出来。 三个重点: 点的表示:我们通过上下两点确定正方形的原则来表示,且点的存储方式一点不能用pair,这样效率及其低下,且难以有一定的自由度取操作 x,y 轴,我们采用哈希表套哈希表的方式取存储! 点的记录:通过嵌套哈希表完成点的次数记录,比如:unordered_map<int, unordered_map<int, int>> cnt; cnt[y][x]++; 点的枚举:通过嵌套哈希表,可以很好的把 x,y 坐标的对应点数给限制住,所以我们要根据这点可以利用count方法直接把不是同一个纵轴的点给排除,比如: res += (colCnt.count(x) ? colCnt[x] : 0) * (yCnt.count(x + d) ? yCnt[x + d] : 0) * (colCnt.count(x + d)? colCnt[x + d] : 0); //一旦以上的count方法返回0,即表示该点不是同一个纵轴上的点,则得出结果0,整个res就相当于没有加任何数字。 再比如通过yCnt提前取出在同一个横轴的点:unordered_map<int, int> & yCnt = cnt[y]; //取和point在同一行的所有点 //这样后续的枚举过程直接可以套用yCnt[x+d]或者yCnt[x-d]来得到对应左右两种情况正方形的点个数。 最后一个优化:由于我们每次枚举同一纵轴上的点不确定是上面还是下面,实际上根本不重要,由于在计算时,我们都会把左右两种正方形的情况给计算完,而这个过程正好是两个相反的 +- 过程,所以无论枚举得到的正方形边长为正还是为负数,都不影响! 解题代码 非常详细的注释了class DetectSquares { public: unordered_map<int, unordered_map<int, int>> cnt; DetectSquares() { } void add(vector<int> point) { int x = point[0], y = point[1]; cnt[y][x]++; } int count(vector<int> point) { int res = 0; int x = point[0], y = point[1]; if (!cnt.count(y)) { return 0; } unordered_map<int, int> & yCnt = cnt[y]; //取和point在同一行的所有点 for (auto & [col, colCnt] : cnt) { if (col != y) {//由于我们构造正方形是根据上下两条边,故此处枚举的另外一点不能在同一行 // 根据对称性,这里可以不用取绝对值,具体而言就是所有情况根据+-已经包括 int d = col - y;//得到正方形边长,根据这个值可以直接取到对应的另外几个点(如果存在的话) //这里的colCnt.count(x)用于判断是否和当前点在同一个纵轴,这样才可能构造上下两边,故下面只要有1个为0,则加的都是0 //由于我们指定了必须是同一个纵轴上的点,所以不可能构造出两个相同的正方形! res += (colCnt.count(x) ? colCnt[x] : 0) * (yCnt.count(x + d) ? yCnt[x + d] : 0) * (colCnt.count(x + d)? colCnt[x + d] : 0); res += (colCnt.count(x) ? colCnt[x] : 0) * (yCnt.count(x - d) ? yCnt[x - d] : 0) * (colCnt.count(x - d) ? colCnt[x - d] : 0); } } return res; } }; 总结 学到以下:如何通过嵌套哈希表表示点,以及用它表示的而不用pair表示的好处。重点好像也就上面那条。
正在初始化 WebAssembly 引擎…
首次编译原生模块可能需要数秒
就绪后,页面交互将以接近原生的速度运行