我确实检查了有关该主题的先前问题,但似乎没有一个能解决该问题。
假设您有4个人:阿卜杜勒,比阿特丽克斯,查理和达里亚。 您想存储有关这些人彼此感觉的信息
Abdul and Beatrix are in love Beatrix and Charlie hate each other Abdul and Charlie are good friends Daria and Beatrix don't know each other etc.
在缺乏诗意的计算机世界中,这可以解释为:
relation (Abdul , Beatrix) = love; relation (Beatrix, Charlie) = hate; relation (Abdul , Charlie) = friendship; etc.
换句话说,如果要映射每对人之间的关系,则将需要一个数据结构,该数据结构可为每对人保持唯一的值。
尽管有许多方法可以实现合适的数据结构,但在某些情况下,您可能希望此表是一个固定大小的数组,该数组由表示给定关系的对直接索引。
定的I Ñ该组中的第一N自然整数的,让我们称之为P Ñ的我所有无序对序列(A,B)ñ使得<> B,排序在字典式顺序。
在(希望如此)隐晦的英语中, P列举了I的两个元素之间的所有可能关系 。
示例(对于N = 4):
I 4 =(0,1,2,3) P 4 =((0,1),(0,2),(0,3),(1,2),(1,3),(2,3 ))
注意,P的基数Ñ是N(N-1)/ 2,所以 P的最紧凑的基于零的索引 Ñ将在[0..N(N-1)/ 2-1]范围。
我们如何以紧凑而有效的方式索引P N?
在其他热水瓶中,
P N的排列方式次要,但按字典顺序排序可能是最方便的。
例:
P 4 =((0,1),(0,2),(0,3),(1,2),(1,3),(2,3)) p 4(1,3)= 4 p 4 -1(4)=(1,3)
到目前为止,我在这里看到的两个答案都可以很好地进行第一个计算,但是向后计算需要循环,这是不必要的。
考虑以下带有的示例n=5,该示例显示了元素的编号方式。
n=5
0 1 2 3 4 +---+---+---+---+---+ 0 | | | | | | +---+---+---+---+---+ 1 | 0 | | | | | +---+---+---+---+---+ 2 | 1 | 4 | | | | +---+---+---+---+---+ 3 | 2 | 5 | 7 | | | +---+---+---+---+---+ 4 | 3 | 6 | 8 | 9 | | +---+---+---+---+---+
给定一个元组(x, y)(假设x < y),列中的第一个索引x由下式给出
(x, y)
x < y
x
n-1 + n-2 + ... + n-x = (n-1 + n-x) * x / 2 = (2n - x - 1) * x / 2
该列中的偏移量仅为y - x - 1。这产生了总表达
y - x - 1
p_n(x, y) = (2n - x - 1) * x / 2 + y-x-1 = (2n - x - 3) * x / 2 + y-1
现在,走另一条路很棘手。我们有一些价值观p,n需要找到x和y。尽管可以通过假设正在寻找列中的第一个单元格来使生活变得更简单y = x+1。如果将其插入上面的公式中,我们将获得
p
n
y
y = x+1
p = (2n - x - 1) * x / 2
重写此公式将得出
x^2 - (2n-1) * x + 2p = 0
这是一个简单的二次方程,可以求解x:
x = [(2n-1) - Sqrt((2n-1)^2 - 8p)] / 2
当然,我们可能高估了x,因为我们假设的可能值最低y。但是,我们相差不远(仍在右列中),因此舍入该值就足以得到real x。
将x我们发现的值代入原始公式中,得出以下公式非常简单y:
x = Floor( [(2n-1) - Sqrt((2n-1)^2 - 8p)] / 2 ) y = p - (2n - x - 3) * x / 2 + 1
可以说,对数字取平方根是很慢的操作(这是正确的),但是对于较大的值,此方法将胜过循环n。