对于一个
n×n 的矩阵,上三角的
(i, j) 元素是矩阵的第
i×(2×n-i+1)/2+j-i 个元素。
我们也可以反过来计算,通过以下公式得到第
k 个元素的
(i, j) 坐标:
i = ⌊(-√((2n+1)2-8k)+2n+1)/2⌋ 和
j = k+i-i×(2×n-i+1)/2
例如:
from math import floor, sqrt
def coor_to_idx(n, i, j):
return i*(2*n-i+1)//2+j-i
def idx_to_coor(n, k):
i = floor((-sqrt((2*n+1)*(2*n+1)-8*k)+2*n+1)/2)
j = k + i - i*(2*n-i+1)//2
return i, j
例如:
>>> [idx_to_coor(4, i) for i in range(10)]
[(0, 0), (0, 1), (0, 2), (0, 3), (1, 1), (1, 2), (1, 3), (2, 2), (2, 3), (3, 3)]
>>> [coor_to_idx(4, i, j) for i in range(4) for j in range(i, 4)]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
考虑到数值并不巨大(如果这些数值很大,计算就不再是常数时间),因此我们可以在O(1)的时间内计算第k个坐标,例如:
>>> idx_to_coor(1234567, 123456789)
(100, 5139)
相当于通过枚举获得它:
>>> next(islice(((i, j) for i in range(1234567) for j in range(i, 1234567)), 123456789, None))
(100, 5139)
在这里,将索引转换为坐标也可能会由于浮点精度问题而产生一些舍入误差,特别是对于大数值。