问题是,给定一个数字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的组合。
答案 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
。