Skip to content

Commit de3e3bd

Browse files
authored
feat: add solutions to lc problem: No.3625 (#4873)
1 parent 63178cb commit de3e3bd

File tree

7 files changed

+722
-8
lines changed

7 files changed

+722
-8
lines changed

solution/3600-3699/3625.Count Number of Trapezoids II/README.md

Lines changed: 248 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -79,32 +79,276 @@ tags:
7979

8080
<!-- solution:start -->
8181

82-
### 方法一
82+
### 方法一:哈希表 + 枚举
83+
84+
我们可以把所有点两两组合,计算出每一对点所对应的直线的斜率和截距,并使用哈希表进行记录,计算斜率相同且截距不同的直线两两组合得到的数量之和。注意,对于平行四边形,我们在上述计算中会被重复计算两次,因此我们需要将其减去。
85+
86+
平行四边形的对角线中点重合,因此我们同样把所有点两两组合,计算出每一对点的中点坐标和斜率,并使用哈希表进行记录,计算斜率相同且中点坐标相同的点对两两组合得到的数量之和。
87+
88+
具体地,我们使用两个哈希表 $\textit{cnt1}$ 和 $\textit{cnt2}$ 分别记录以下信息:
89+
90+
- 其中 $\textit{cnt1}$ 记录斜率 $k$ 和截距 $b$ 出现的次数,键为斜率 $k$,值为另一个哈希表,记录截距 $b$ 出现的次数;
91+
- 其中 $\textit{cnt2}$ 记录点对的中点坐标和斜率 $k$ 出现的次数,键为点对的中点坐标 $p$,值为另一个哈希表,记录斜率 $k$ 出现的次数。
92+
93+
对于点对 $(x_1, y_1)$ 和 $(x_2, y_2)$,我们记 $dx = x_2 - x_1$,并且 $dy = y_2 - y_1$。如果 $dx = 0$,则说明两点在同一条垂直线上,我们记斜率 $k = +\infty$,截距 $b = x_1$;否则斜率 $k = \frac{dy}{dx}$,截距 $b = \frac{y_1 \cdot dx - x_1 \cdot dy}{dx}$。点对的中点坐标 $p$ 可以表示为 $p = (x_1 + x_2 + 2000) \cdot 4000 + (y_1 + y_2 + 2000)$,这里加上偏移量是为了避免负数。
94+
95+
接下来,我们遍历所有点对,计算出对应的斜率 $k$、截距 $b$ 和中点坐标 $p$,并更新哈希表 $\textit{cnt1}$ 和 $\textit{cnt2}$。
96+
97+
然后,我们遍历哈希表 $\textit{cnt1}$,对于每一个斜率 $k$,我们计算所有截距 $b$ 出现次数的两两组合之和,并累加到答案中。最后,我们遍历哈希表 $\textit{cnt2}$,对于每一个中点坐标 $p$,我们计算所有斜率 $k$ 出现次数的两两组合之和,并从答案中减去。
98+
99+
时间复杂度 $O(n^2)$,空间复杂度 $O(n^2)$。其中 $n$ 是点的数量。
83100

84101
<!-- tabs:start -->
85102

86103
#### Python3
87104

88105
```python
89-
106+
class Solution:
107+
def countTrapezoids(self, points: List[List[int]]) -> int:
108+
n = len(points)
109+
110+
# cnt1: k -> (b -> count)
111+
cnt1: dict[float, dict[float, int]] = defaultdict(lambda: defaultdict(int))
112+
# cnt2: p -> (k -> count)
113+
cnt2: dict[int, dict[float, int]] = defaultdict(lambda: defaultdict(int))
114+
115+
for i in range(n):
116+
x1, y1 = points[i]
117+
for j in range(i):
118+
x2, y2 = points[j]
119+
dx, dy = x2 - x1, y2 - y1
120+
121+
if dx == 0:
122+
k = 1e9
123+
b = x1
124+
else:
125+
k = dy / dx
126+
b = (y1 * dx - x1 * dy) / dx
127+
128+
cnt1[k][b] += 1
129+
130+
p = (x1 + x2 + 2000) * 4000 + (y1 + y2 + 2000)
131+
cnt2[p][k] += 1
132+
133+
ans = 0
134+
135+
for e in cnt1.values():
136+
s = 0
137+
for t in e.values():
138+
ans += s * t
139+
s += t
140+
141+
for e in cnt2.values():
142+
s = 0
143+
for t in e.values():
144+
ans -= s * t
145+
s += t
146+
147+
return ans
90148
```
91149

92150
#### Java
93151

94152
```java
95-
153+
class Solution {
154+
public int countTrapezoids(int[][] points) {
155+
int n = points.length;
156+
Map<Double, Map<Double, Integer>> cnt1 = new HashMap<>(n * n);
157+
Map<Integer, Map<Double, Integer>> cnt2 = new HashMap<>(n * n);
158+
159+
for (int i = 0; i < n; ++i) {
160+
int x1 = points[i][0], y1 = points[i][1];
161+
for (int j = 0; j < i; ++j) {
162+
int x2 = points[j][0], y2 = points[j][1];
163+
int dx = x2 - x1, dy = y2 - y1;
164+
double k = dx == 0 ? Double.MAX_VALUE : 1.0 * dy / dx;
165+
double b = dx == 0 ? x1 : 1.0 * (y1 * dx - x1 * dy) / dx;
166+
if (k == -0.0) {
167+
k = 0.0;
168+
}
169+
if (b == -0.0) {
170+
b = 0.0;
171+
}
172+
cnt1.computeIfAbsent(k, _ -> new HashMap<>()).merge(b, 1, Integer::sum);
173+
int p = (x1 + x2 + 2000) * 4000 + (y1 + y2 + 2000);
174+
cnt2.computeIfAbsent(p, _ -> new HashMap<>()).merge(k, 1, Integer::sum);
175+
}
176+
}
177+
178+
int ans = 0;
179+
for (var e : cnt1.values()) {
180+
int s = 0;
181+
for (int t : e.values()) {
182+
ans += s * t;
183+
s += t;
184+
}
185+
}
186+
for (var e : cnt2.values()) {
187+
int s = 0;
188+
for (int t : e.values()) {
189+
ans -= s * t;
190+
s += t;
191+
}
192+
}
193+
return ans;
194+
}
195+
}
96196
```
97197

98198
#### C++
99199

100200
```cpp
101-
201+
class Solution {
202+
public:
203+
int countTrapezoids(vector<vector<int>>& points) {
204+
int n = points.size();
205+
unordered_map<double, unordered_map<double, int>> cnt1;
206+
unordered_map<int, unordered_map<double, int>> cnt2;
207+
208+
cnt1.reserve(n * n);
209+
cnt2.reserve(n * n);
210+
211+
for (int i = 0; i < n; ++i) {
212+
int x1 = points[i][0], y1 = points[i][1];
213+
for (int j = 0; j < i; ++j) {
214+
int x2 = points[j][0], y2 = points[j][1];
215+
int dx = x2 - x1, dy = y2 - y1;
216+
double k = (dx == 0 ? 1e9 : 1.0 * dy / dx);
217+
double b = (dx == 0 ? x1 : 1.0 * (1LL * y1 * dx - 1LL * x1 * dy) / dx);
218+
219+
cnt1[k][b] += 1;
220+
int p = (x1 + x2 + 2000) * 4000 + (y1 + y2 + 2000);
221+
cnt2[p][k] += 1;
222+
}
223+
}
224+
225+
int ans = 0;
226+
for (auto& [_, e] : cnt1) {
227+
int s = 0;
228+
for (auto& [_, t] : e) {
229+
ans += s * t;
230+
s += t;
231+
}
232+
}
233+
for (auto& [_, e] : cnt2) {
234+
int s = 0;
235+
for (auto& [_, t] : e) {
236+
ans -= s * t;
237+
s += t;
238+
}
239+
}
240+
return ans;
241+
}
242+
};
102243
```
103244

104245
#### Go
105246

106247
```go
248+
func countTrapezoids(points [][]int) int {
249+
n := len(points)
250+
cnt1 := make(map[float64]map[float64]int, n*n)
251+
cnt2 := make(map[int]map[float64]int, n*n)
252+
253+
for i := 0; i < n; i++ {
254+
x1, y1 := points[i][0], points[i][1]
255+
for j := 0; j < i; j++ {
256+
x2, y2 := points[j][0], points[j][1]
257+
dx, dy := x2-x1, y2-y1
258+
259+
var k, b float64
260+
if dx == 0 {
261+
k = 1e9
262+
b = float64(x1)
263+
} else {
264+
k = float64(dy) / float64(dx)
265+
b = float64(int64(y1)*int64(dx)-int64(x1)*int64(dy)) / float64(dx)
266+
}
267+
268+
if cnt1[k] == nil {
269+
cnt1[k] = make(map[float64]int)
270+
}
271+
cnt1[k][b]++
272+
273+
p := (x1+x2+2000)*4000 + (y1 + y2 + 2000)
274+
if cnt2[p] == nil {
275+
cnt2[p] = make(map[float64]int)
276+
}
277+
cnt2[p][k]++
278+
}
279+
}
280+
281+
ans := 0
282+
for _, e := range cnt1 {
283+
s := 0
284+
for _, t := range e {
285+
ans += s * t
286+
s += t
287+
}
288+
}
289+
for _, e := range cnt2 {
290+
s := 0
291+
for _, t := range e {
292+
ans -= s * t
293+
s += t
294+
}
295+
}
296+
return ans
297+
}
298+
```
107299

300+
#### TypeScript
301+
302+
```ts
303+
function countTrapezoids(points: number[][]): number {
304+
const n = points.length;
305+
306+
const cnt1: Map<number, Map<number, number>> = new Map();
307+
const cnt2: Map<number, Map<number, number>> = new Map();
308+
309+
for (let i = 0; i < n; i++) {
310+
const [x1, y1] = points[i];
311+
for (let j = 0; j < i; j++) {
312+
const [x2, y2] = points[j];
313+
const [dx, dy] = [x2 - x1, y2 - y1];
314+
315+
const k = dx === 0 ? 1e9 : dy / dx;
316+
const b = dx === 0 ? x1 : (y1 * dx - x1 * dy) / dx;
317+
318+
if (!cnt1.has(k)) {
319+
cnt1.set(k, new Map());
320+
}
321+
const mapB = cnt1.get(k)!;
322+
mapB.set(b, (mapB.get(b) || 0) + 1);
323+
324+
const p = (x1 + x2 + 2000) * 4000 + (y1 + y2 + 2000);
325+
326+
if (!cnt2.has(p)) {
327+
cnt2.set(p, new Map());
328+
}
329+
const mapK = cnt2.get(p)!;
330+
mapK.set(k, (mapK.get(k) || 0) + 1);
331+
}
332+
}
333+
334+
let ans = 0;
335+
for (const e of cnt1.values()) {
336+
let s = 0;
337+
for (const t of e.values()) {
338+
ans += s * t;
339+
s += t;
340+
}
341+
}
342+
for (const e of cnt2.values()) {
343+
let s = 0;
344+
for (const t of e.values()) {
345+
ans -= s * t;
346+
s += t;
347+
}
348+
}
349+
350+
return ans;
351+
}
108352
```
109353

110354
<!-- tabs:end -->

0 commit comments

Comments
 (0)