我有一个数字n
,我的程序用它来表示大小为n
:的自然数列表
[0,1,2] // n=3
[0,1,2,3,4,5] // n=6
列表总是以0
开头,并且它们的元素按顺序显示,不跳过任何数字。最后一个元素始终是(n-1)
。
现在,我需要获得这些数组的唯一元素对。因此,我编写了一个算法,将n
作为输入,并从上面的对应项返回一个由唯一元素对组成的数组。
[[0,1],[0,2],[1,2]] // n=3
[[0,1],[0,2],[0,3],[0,4],[0,5],[1,2],[1,3],[1,4],[1,5],[2,3],[2,4],[2,5],[3,4],[3,5],[4,5]] // n=6
在该实现中,元素不能与其自身配对(例如[0,0]
(。对[1,2]
被认为等同于[2,1]
,因此只有前者会出现。
然而,由于这些对具有一致的排序并遵循基本模式,我怀疑有一些数字公式可以直接用于计算它们的值,而无需通过编程创建它们的列表。
我想要的是一个函数f(n,i)
,它会给我n
的对数组中第10对CCD_中的值,例如:
f(3,2) => [1,2]
f(6,8) => [1,5]
或者,也可以有两个函数:一个是g(n,i)
,它返回第一个pair元素,另一个h(n,i)
,它返回第二个。像这样:
g(3,2) => 1
h(3,2) => 2
g(6,8) => 1
h(6,8) => 5
有没有一个公式可以计算这些数字?
注意:我不是在寻找生成组合数组的算法。我已经有了。我希望避免生成数组组合,只需直接用数字计算组合值。
f(n, i):
m = (n - 1) * n / 2 # error check i <= m
i = m - i # zero-based index
t = floor((sqrt(8 * i + 1) - 1) / 2)
r = i - t * (t + 1) / 2
[n - t - 2, n - r - 1]
诀窍是从最后开始倒计数。否则,你基本上是在寻找i
之前的三角形数,并相对于它进行计算。
维基百科有许多关于三角根的属性,包括上面用来推导三角根的公式。
倒三角数的基本思想归功于@shawnt00;我用x = (sqrt(8*i + 1) - 1)//2
作为三角根,计算出了。
def find(n, i):
m = n * (n - 1) // 2
i = m - i - 1
t = (sqrt(8 * i + 1) - 1)//2
return (n - t - 2, n - 1 - (i - t * (t + 1) // 2))