【算法刷题-第8题】力扣-同积元组

目录

题目

示例

题解

代码

补充:


题目

给你一个由 不同 正整数组成的数组 nums ,请你返回满足 a * b = c * d 的元组 (a, b, c, d) 的数量。其中 abc 和 d 都是 nums 中的元素,且 a != b != c != d 。

示例

输入:nums = [2,3,4,6]
输出:8
解释:存在 8 个满足题意的元组:
(2,6,3,4) , (2,6,4,3) , (6,2,3,4) , (6,2,4,3)
(3,4,2,6) , (4,3,2,6) , (3,4,6,2) , (4,3,6,2)

示例 2:

输入:nums = [1,2,4,5,10]
输出:16
解释:存在 16 个满足题意的元组:
(1,10,2,5) , (1,10,5,2) , (10,1,2,5) , (10,1,5,2)
(2,5,1,10) , (2,5,10,1) , (5,2,1,10) , (5,2,10,1)
(2,10,4,5) , (2,10,5,4) , (10,2,4,5) , (10,2,4,5)
(4,5,2,10) , (4,5,10,2) , (5,4,2,10) , (5,4,10,2)

题解

1. 这题主要就是组合数学,不同数之间的排列组合

2. 我们先来回忆一下我们高中学习的排列组合:

        四个数,排列四个位置,一共有多少种排列方式?

                

        我们可以看到,第一个位置有4种选法,第二个位置有3种选法,以此类推......

        一共就是 4x3x2x1 = 24种

3. 好的,我们现在来看这道题,拿到这一题,我们第一个想法应该是枚举出每两个数字的和,然后进行统计,如果你这个和只有一个,那肯定无法构成a*b = c * d

4. 于是我们通过哈希表也就是字典的形式,键为总和,值为数量

5. 我们先来看样例:

        [2,3,4,6]

        我们可以看到,2*6 = 3*4

        也就是12的值有2个,然后利用组合,我们有两组数字,要把这两组数字放在四个位置,并且要符合{a,b,c,d},于是要从这两组数据开始组合,就是C22,如果有n组数据,就是Cn2,从n个选2个出来进行组合

6. 然后我们分成两组,2 6 和3  4,这两组内的数据不能与其他组交换,不然值就不对了,保证a * b = c * d

7. 我们元组为{a,b,c,d},也就是分成a,b和c,        d两个组,我们要从26和34两个组选一个去a,b组,然后剩下一个就定了,也就是C21

8. 去到那个组之后,内部还可以排序,也就是一个当a,一个当b,或者反过来,也就是有序的排列要用A22,然后有两个组,所以还要乘2

最后排列组合数就为:C21 * A22 * A22 = 8(也就是两组数字ab = cd,他们最后能够组合的数量)

9. 当然别忘了,前面是只有两组数据的和为12,也就是C22,如果我们有三组数相乘都等于同一个数的话,就需要从那三组数选两组出来,这样才满足a *b = c* d,也就是C32,最后就是C32 * C21 * A22 * A22

从而推导: n组就是   Cn2 * C21 * A22 * A22

简化一下就是Cn2 * 8

10。 最后将这些数相加就是最后的结果啦

代码

class Solution:
    def tupleSameProduct(self, nums: List[int]) -> int:
        dic = {}
        l = len(nums)
        # 枚举出所有数的和
        for i in range(0,l-1):
            for j in range(i,l):
                if nums[i]!=nums[j]:
                    dic[nums[i] * nums[j]] = 0
        for i in range(0,l-1):
            for j in range(i,l):
                if nums[i]!=nums[j]:
                    dic[nums[i] * nums[j]] += 1
        num = 0
        # 开始组合
        for v in dic.values():
            if v >= 2:
               num += v*(v-1)//2 * 8   # 这个8其实就是C21 * A22 * A22,两组的排列组合数
        return num 

补充:

Cmn = m!/ (n! * (m-n)!)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

jiaoxingk

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值