考虑以下问题。给定是长度为n的数组P,表示双射。即元素0< = i< n映射到P [i]。
鉴于P是一个置换,它可以用周期表示法编写,如例如here所述。
例如,如果
P = [16, 3, 10, 6, 5, 9, 1, 19, 13, 14, 7, 0, 2, 8, 12, 4, 17, 15, 11, 18]
然后循环符号的结果将是
[(16, 17, 15, 4, 5, 9, 14, 12, 2, 10, 7, 19, 18, 11, 0), (3, 6, 1), (13, 8)]
以下是完成此操作的Python方法
def toCycle(p):
covered = cur = 0
perm = []
n = len(p)
done = [0]*n
while covered < n:
while cur < n and done[cur] == -1:
cur+=1
cycle = [p[cur]]
sec = p[p[cur]]
done[p[cur]] = -1
done[cur] = -1
covered+=1
while sec != cycle[0]:
cycle.append(sec)
done[sec] = -1
sec = p[sec]
covered+=1
perm+=[tuple(cycle)]
return perm
算法明确地以线性时间运行(完成/ p的每个元素被访问的次数是恒定的),因此没有太多可以渐近地完成。
由于我必须在大量的大排列上使用这种方法,我想知道
你能加快速度吗?你对表现有什么建议吗? 改进?
答案 0 :(得分:1)
def cycling(p, start, done):
while not done[e]:
done[e] = True
e = p[e]
yield e
def toCycle(p):
done = [False]*len(p)
cycles = [tuple(cycling(p, 0, done))]
while not all(done):
start = done.index(False)
cycles.append(tuple(cycling(p, start, done)))
return cycles
使用您的示例,我的代码运行速度比您的快30%。