Leetcode 3625. Count Number of Trapezoids II

1. 解题思路

这一题和题目3623. Count Number of Trapezoids I很像,不过难度在于不要求边平行于x轴了,而是任意方向上的梯形都可以。

因此,思路上我们就是首先遍历一下所有的线段,计算出其所处的直线 ( k , b ) (k, b) (k,b),然后我们只需要取斜率 k k k相同,而 b b b不同的任意两条直线,其上的所有线段的乘积即为当前方向上的梯形的个数。

不过,需要注意的是,在这里,如果选取的梯形事实上是一个平行四边形,那么它就会在两个平行方向上各自被count一次,就会导致结果错误,因此我们需要从返回的结果当中减去图中的所有平行四边形的个数。

而如果计算平行四边形的个数,问了一下deepseek之后倒是给出了一个简单的思路,就是计算所有的线段的中点,只要中点相同,那么对应的两条线段就必然可以构成一个平行四边形,除非其恰好共线。

因此,我们使用上述方式减去所有的平行四边形之后,只需要找到所有的共线点,然后考察其可以构成多少个“平行四边形”,然后将对应的数加回去即可。

2. 代码实现

给出python代码实现如下:

class Solution:
    def countTrapezoids(self, points: List[List[int]]) -> int:
        n = len(points)

        def cal_line(i, j):
            x1, y1 = points[i]
            x2, y2 = points[j]
            k = (y1-y2)/(x1-x2) if x1 != x2 else 1e9
            b = (x2*y1-x1*y2) / (x1-x2) if x1 != x2 else x1
            return (k, b)

        edges = defaultdict(lambda: defaultdict(int))
        lines = defaultdict(set)
        for i in range(n-1):
            for j in range(i+1, n):
                k, b = cal_line(i, j)
                edges[k][b] += 1
                lines[(k,b)].add(i)
                lines[(k,b)].add(j)
        if len(edges) == 1:
            return 0
        
        ans = 0
        for k, bs in edges.items():
            bs = list(bs.values())
            m = len(bs)
            for i in range(m-1):
                n1 = bs[i]
                for j in range(i+1, m):
                    n2 = bs[j]
                    ans += n1 * n2

        def count_parallelograms(points):
            n = len(points)
            # 哈希表记录每个中点(存储2倍值避免浮点误差)的出现次数
            midpoint_count = defaultdict(int)
            
            # 遍历所有点对 (i, j) 其中 i < j
            for i in range(n):
                x1, y1 = points[i]
                for j in range(i + 1, n):
                    x2, y2 = points[j]
                    # 计算中点*2(整数存储避免除法)
                    mx = x1 + x2
                    my = y1 + y2
                    midpoint_count[(mx, my)] += 1
            
            # 统计平行四边形总数
            total = 0
            for count in midpoint_count.values():
                if count >= 2:
                    # 组合公式 C(count, 2) = count*(count-1)//2
                    total += count * (count - 1) // 2
            return total

        dup = count_parallelograms(points)
        for line in lines.values():
            _points = [points[i] for i in line]
            if len(_points) >= 4:
                dup -= count_parallelograms(_points)
        return ans - dup

提交代码评测得到:耗时2392ms,占用内存126.76MB。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值