【力扣周赛题解】Count Number of Trapezoids II
📚 本文用最简单的方式,带你理解这道力扣周赛几何题!
📌 什么是梯形?
在开始之前,让我们先回忆一下初中数学:
上底
┌─────────┐
/ \
/ \
/ \
└─────────────────┘
下底
梯形 = 有且只有一对平行边的四边形
但这道题更宽松一点:只要有至少一对平行边就算梯形(包括平行四边形)
🎯 题目说了啥?
简单版本:给你一堆点,从中选 4 个点,看能组成多少个梯形?
举个例子:平面上有这些点
●A ●B
●C ●D
●E ●F
我们要找出所有能组成梯形的 4 点组合!
🤔 怎么判断两条线平行?
还记得初中学的吗?斜率相同的两条线平行!
斜率 = 上升的高度 ÷ 水平移动的距离
= (y₂ - y₁) ÷ (x₂ - x₁)
看图理解:
●B(4,3)
/
/ ↑ 上升2格
/ |
●A(2,1) ────→
水平走2格
斜率 = 2 ÷ 2 = 1
如果两条线段的斜率一样,它们就是平行的!
线段1:斜率 = 1
●───────●
← 这两条线平行!
●───────●
线段2:斜率 = 1
💡 解题思路(大白话版)
第一步:找出所有的线段
假设有 4 个点 A、B、C、D,那我们可以画出 6 条线段:
AB AC AD BC BD CD
就像这样:
A●─────────●B
|\ /|
| \ / |
| \ / |
| \ / |
| X |
| / \ |
| / \ |
| / \ |
|/ \|
C●─────────●D
第二步:把斜率相同的线段放一起
就像整理书架一样,把"方向相同"的线段归类:
📁 斜率 = 0 的文件夹(水平线)
├── 线段 AB(上边)
└── 线段 CD(下边)
📁 斜率 = ∞ 的文件夹(垂直线)
├── 线段 AC(左边)
└── 线段 BD(右边)
📁 斜率 = -1 的文件夹(↘ 方向)
└── 线段 AD(左上到右下的对角线)
📁 斜率 = 1 的文件夹(↗ 方向)
└── 线段 BC(右上到左下的对角线,反过来看就是↗)
第三步:在每个文件夹里找"配对"
同一个文件夹里的线段都是平行的!
每选 2 条线段,就可能组成一个梯形的"上底和下底"!
从"斜率=0"文件夹里选 AB 和 CD:
A●───────────●B ← 上底
| |
| |
C●───────────●D ← 下底
👆 这就是一个梯形(其实是长方形)!
⚠️ 但是!有些情况不能算
情况1:两条线段在同一条直线上 ❌
●────●────●────●
A B C D
线段 AB 和 CD 虽然平行,但在同一条线上!
这样选 4 个点,它们排成一排,组不成四边形!
情况2:两条线段共用一个端点 ❌
●B
/
●A
\
●C
线段 AB 和 AC 共用了点 A
这样只有 3 个点,组不成四边形!
情况3:平行四边形会被数两次 ⚠️
●───────────●
| |
| |
●───────────●
这个图形有两对平行边!
- 上下两条边平行 → 数了 1 次
- 左右两条边平行 → 又数了 1 次
所以要减掉重复的!
🧮 完整计算步骤
让我们一步步算出答案:
第 1 步:在每个斜率文件夹里数配对
假设某个文件夹里有 k 条线段,从中选 2 条的方法数是:
C(k,2) = k × (k-1) ÷ 2
例如:有 4 条线段,选 2 条 = 4 × 3 ÷ 2 = 6 种选法
第 2 步:减掉不合法的情况
❌ 减掉「共线」的配对
(两条线段在同一条直线上)
❌ 减掉「共端点」的配对
(两条线段共用一个点)
✅ 但是!如果既共线又共端点,被减了两次,要加回来一次
第 3 步:减掉平行四边形的重复计数
平行四边形有 2 对平行边,被数了 2 次
所以最后要 - 平行四边形数量
📐 最终公式
┌────────────────────────────────────────────────────────────────┐
│ │
│ 对于每个斜率文件夹: │
│ │
│ 有效配对数 = C(k,2) │
│ - 共线的配对数 │
│ - 共端点的配对数 │
│ + 既共线又共端点的配对数(加回来) │
│ │
│ ───────────────────────────────────────────── │
│ │
│ 答案 = 所有文件夹的有效配对数之和 - 平行四边形数量 │
│ │
└────────────────────────────────────────────────────────────────┘
💡 这个"减了又加回来"的技巧叫做容斥原理,是组合数学中常用的方法!
🎨 完整例子
假设有 5 个点:
●(0,2) ●(4,2)
●(0,0) ●(2,0) ●(4,0)
Step 1: 找所有线段并分类
| 线段 | 斜率 |
|---|---|
| (0,0)-(4,0) | 0(水平) |
| (0,0)-(2,0) | 0(水平) |
| (2,0)-(4,0) | 0(水平) |
| (0,2)-(4,2) | 0(水平) |
| (0,0)-(0,2) | ∞(垂直) |
| (4,0)-(4,2) | ∞(垂直) |
| ... | ... |
Step 2: 在"水平线"文件夹里找配对
排除掉在同一条直线上的(比如下面那 3 条线段都在 y=0 这条线上)
有效配对:上面那条线 + 下面某条线 = 梯形!
Step 3: 数一数,得出答案!
🔑 编程小技巧
怎么避免小数?
斜率可能是 0.333333... 这样的无限小数,计算机算不准!
解决方法:用分数表示斜率!
比如斜率 = 2/6
不要算成 0.333...
而是约分成 1/3,存成 (1, 3) 这对数字
怎么判断平行四边形?
平行四边形有个特点:两条对角线的中点重合!
A●─────────────●B
\ /
\ /
\ /
\ /
\ /
\ /
● ← 对角线 AD 和 BC 在此相交,中点重合!
/ \
/ \
/ \
/ \
/ \
C●─────────────●D
换一种方式理解:
对角线 AD 的中点 = ( (Ax+Dx)/2, (Ay+Dy)/2 )
对角线 BC 的中点 = ( (Bx+Cx)/2, (By+Cy)/2 )
如果这两个中点相同 → 这 4 个点组成平行四边形!
所以我们只要:
- 算出每对点的中点
- 如果有两对点中点相同,它们就能组成平行四边形!
⏱️ 这个方法快吗?
| 点的数量 | 大约要算多少次 |
|---|---|
| 10 个点 | 100 次 |
| 100 个点 | 10,000 次 |
| 500 个点 | 250,000 次 |
对计算机来说,25 万次计算简直是小菜一碟!✅
📝 总结
解题三步走:
┌──────────────┐
│ 1️⃣ 枚举线段 │
│ 找出所有两点 │
│ 组成的线段 │
└──────┬───────┘
↓
┌──────────────┐
│ 2️⃣ 按斜率分组 │
│ 斜率相同的 │
│ 放一起 │
└──────┬───────┘
↓
┌──────────────┐
│ 3️⃣ 配对计数 │
│ 排除不合法的 │
│ 减去重复的 │
└──────────────┘
🎉 恭喜你看完了!
这道题结合了:
- 📐 几何知识:斜率、平行、中点
- 🧠 算法思维:分类、配对、去重
- 💻 编程技巧:避免小数、用哈希表分组
是不是没有想象中那么难呢?😄
💬 如果觉得有帮助,欢迎点赞收藏!有问题可以在评论区讨论~