我的数据结构是由城市列表代表的路径。例如,如果城市是
var editorAreas = {}
$('#c-success-tabs-content .tab-pane').each(function(){
var successID = $(this).attr('data-id');
successesList.push(successID);
editorAreas[successID] = new Edicy.TextEditorView({el: $('.foo')});
editorAreas[successID].editor.on('aftercommand:composer', function() {
pageData.set('key', 'value');
});
});
for(var id in editorAreas){
console.log(id, editorAreas[id])
}
可能的配置可能是:A, B, C, D
或A, B, D, C
。
我需要两个比较两个路径才能找到这两个路径之间的差异,这样这个过程的输出就会返回将第二个路径转换为第一个路径所需的一组交换操作。
例如,给定以下路径:
D, C, A, B
将路径X = {A, B, D, C}
Y = {D, C, A, B}
indexes = {0, 1, 2, 3}
转换为Y
的一种可能方法是进行以下互换:X
。
{0-2, 1-3}
是否有任何已知(和快速)算法允许计算此集合?
答案 0 :(得分:3)
您的问题看起来像是计算最小数量的互换以将一个排列转换为另一个排列的问题。
事实上,这是一个众所周知的问题。关键的想法是创建新的排列P
,P[i]
是X[i]
中Y
城市的索引。然后,您只需计算C
中的总周期数P
。答案是len(X) - C
,其中len(X)
的大小为X
。
在您的情况下,P
看起来像是:3, 4, 1, 2
。它有两个周期:3, 1
和4, 2
。所以答案是4 - 2 = 2
。
总复杂度是线性的。
有关详细信息,请参阅this answer。它更详细地解释了这个算法。
修改强>
好的,但我们如何才能获得互换,而不仅仅是他们的数量?请注意,在此解决方案中,如果周期长度为N - 1
,我们会独立地对每个周期进行重新排序N
交换。因此,如果您有周期v(0), v(1), ..., v(N - 1), v(N)
,则只需要交换v(N), v(N - 1)
,v(N - 1), v(N - 2)
,...,v(1), v(0)
。所以你以相反的顺序交换循环元素。
此外,如果您的C
周期长度为L(1), L(2), ..., L(C)
,则互换次数为L(1) - 1 + L(2) - 1 + ... + L(C) - 1 = L(1) + L(2) + ... + L(C) - C = LEN - C
,其中LEN
为排列长度。