在满足特定要求的序列中找出三个数字的组合数量

时间:2019-02-13 16:30:21

标签: algorithm

问题是,给定一个数字D和一个数量为N的数字序列,请找出三个最大差值不超过D的数字组合的数量。例如:

D = 3, N = 4
Sequence of numbers: 1 2 3 4

Possible combinations: 1 2 3 (3-1 = 2 <= D), 1 2 4 (4 - 1 = 3 <= D), 1 3 4, 2 3 4.

Output: 4 

我所做的:link

好吧,我的概念是:遍历整个数字序列,并找到减去与当前比较数字相比D值最小的最小数字。然后,找到这两个数字之间的组合,并且当前比较的数字为固定值(这意味着n [两个数字之间的数字]的组合取2)。如果即使是序列中最大的数字减去当前比较的数字也没有超过D,则可以使用3个整体元素的组合。

N可以最大为10 ^ 5,最小为1,D可以最大为10 ^ 9,最小为1。

我的算法存在问题:当我将1st元素和10 ^ 5th元素组合在一起时会发生溢出。我怎样才能解决这个问题?有没有一种方法可以在不实际进行阶乘的情况下计算出大量的组合?

编辑:

在最坏的情况下会发生溢出:当前比较的数字仍在索引0中,而所有其他数字都减去当前比较的数字仍小于D。例如,索引0处的数字值为{{ 1}},索引10 ^ 5处的数字值为1,D为10^5 + 1。然后,我的算法将尝试计算10^9的阶乘,然后该阶乘溢出。阶乘将用于计算10 ^ 5取3的组合。

2 个答案:

答案 0 :(得分:1)

当您在排序列表中寻找值范围为D的项目并获得索引差M时,则应计算C(M,3)

但是对于这样的组合编号,您不需要使用大量的阶乘:

 C(M,3) = M! / (6 * (M-3)!) = M * (M-1) * (M-2) / 6

要进一步减少中间结果:

 A = (M - 1) * (M - 2) / 2
 A = (A * M) / 3

答案 1 :(得分:1)

您没有在问题中添加C ++标记,所以让我用Python 3编写答案(应该很容易将其转换为C ++):

N = int(input("N = "))
D = int(input("D = "))
v = [int(input("v[{}] = ".format(i))) for i in range (0, N)]

count = 0
i, j = 0, 1
while j + 1 < N:
    j += 1
    while v[j] - v[i] > D:
        i += 1
    d = j - i
    if d >= 2:
        count += (d - 1) * d // 2  # // is the integer division

print(count)

这个想法是将三元组j的较高索引向上移动,同时将较低索引i拖动到最大距离j-i=d,其中v[j]-v[i]<=D。对于每个i-j对,都有1+2+3+...+d-1个可能的三元组,将j固定,即(d-1)*d/2