leetcode 3625

3625: 统计梯形的数目Ⅱ

思路:

  1. 本题 n≤500,我们可以 O(n^2) 枚举所有点对组成的直线,计算直线的斜率和截距。
  2. 把斜率相同的直线放在同一组,可以从中选择一对平行边,作为梯形的顶边和底边。(去除共线)
  3. 第二步把平行四边形重复统计了一次,所以还要减去任意不共线四点组成的平行四边形的个数。(去除共线)

注意++计算梯形个数++ 我们用的是顶边和底边,++计算平行四边形个数++我们用的是对角线。

复制代码
unordered_map<double,map<double,int>> cnt; 
unordered_map<int,map<double,int>> cnt2; 

嵌套写法↑

复制代码
double k=dx? 1.0*dy/dx: DBL_MAX;
double b=dx? 1.0*(y*dx-x*dy)/dx: x;

若 dx = 0(垂直),把 k 标记成 DBL_MAX(一个不可能与任何正常斜率冲突的特大数)

DBL_MAXdouble 类型,它定义在 <cfloat> / <float.h> 里,是 double 能表示的最大有限值(≈1.79769e+308)

dx? 在 C/C++ ,0 被视为 false,非 0 被视为 true

  • dx != 0 时走 A 分支(非垂直)
  • dx == 0 时走 B 分支(垂直)

1.0*dy/dx 强制整个表达式按 double 精度计算,防止"整数除法"把结果截断成整数。

复制代码
int mid=(x+x2+2000)<<16 | (y+y2+2000); 
  • 4 <= points.length <= 500
  • --1000 <= xi, yi <= 1000 (题目设定)

int 一般认为是32bit,高16位为横坐标,低16位为纵坐标->把二维坐标压缩成一个 int

复制代码
class Solution {
public:
    int countTrapezoids(vector<vector<int>>& points) {
        // 经测试,哈希表套 map 比哈希表套哈希表更快(分组后,每一组的数据量比较小,小数据下 map 比哈希表快)
        unordered_map<double,map<double,int>> cnt; // 斜率 -> 截距 -> 梯形个数
        unordered_map<int,map<double,int>> cnt2; // 中点 -> 斜率 -> 平行四边形个数

        int n=points.size();
        for(int i=0;i<n;i++){
            int x=points[i][0],y=points[i][1]; //剔除共线
            for(int j=0;j<i;j++){
                int x2=points[j][0],y2=points[j][1];
                int dx=x-x2,dy=y-y2;
                double k=dx? 1.0*dy/dx: DBL_MAX;
                double b=dx? 1.0*(y*dx-x*dy)/dx: x;
                cnt[k][b]++;
                int mid=(x+x2+2000)<<16 | (y+y2+2000); // 把二维坐标压缩成一个 int
                cnt2[mid][k]++;
            }
        }
        int ans=0;
        for(auto& [_,m] :cnt){
            int s=0;
            for(auto& [_,c] :m){
                ans+=s*c;
                s+=c;
            }
        }

        for(auto& [_,m] :cnt2){
            int s=0;
            for(auto& [_,c] :m){
                ans-=s*c; // 平行四边形会统计两次,减去多统计的一次  
                s+=c;
            }
        }

        return ans;
    }
};
相关推荐
不能只会打代码1 小时前
力扣--3625. 统计梯形的数目 II 代码解析(Java,详解附注释附图)
算法·leetcode·职场和发展·力扣
练习时长一年1 小时前
LeetCode热题100(岛屿数量)
算法·leetcode·职场和发展
无限进步_1 小时前
基于单向链表的C语言通讯录实现分析
c语言·开发语言·数据结构·c++·算法·链表·visual studio
老鱼说AI1 小时前
算法初级教学第四步:栈与队列
网络·数据结构·python·算法·链表
客梦1 小时前
数据结构核心内容
数据结构·笔记
FMRbpm1 小时前
栈练习--------有效的括号(LeetCode 20)
数据结构·c++·leetcode·新手入门
ReinaXue1 小时前
快速认识图像生成算法:VAE、GAN 和 Diffusion Models
图像处理·人工智能·神经网络·算法·生成对抗网络·计算机视觉·语言模型
再睡一夏就好1 小时前
进程调度毫秒之争:详解Linux O(1)调度与进程切换
linux·运维·服务器·c++·算法·哈希算法
无限进步_1 小时前
C语言双向循环链表实现详解:哨兵位与循环结构
c语言·开发语言·数据结构·c++·后端·算法·链表