对于一个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]
鉴于数字并不大(如果这些数字很大,则计算不再在恒定时间内完成),因此我们可以计算 k-th 坐标 O(1) ,例如:
>>> 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)
此处将索引转换为坐标也可能会由于浮点不精确而产生一些舍入误差。