我得到了元素的排列,{1, 2, 3, ..., N}
我必须使用交换操作对其进行排序。交换元素 x, y 的操作的成本为 min(x,y)。
我需要找出排序排列的最低成本。我坚持使用交换操作N
将1
每个元素放在它的位置上,但这不是一个好主意。
我得到了元素的排列,{1, 2, 3, ..., N}
我必须使用交换操作对其进行排序。交换元素 x, y 的操作的成本为 min(x,y)。
我需要找出排序排列的最低成本。我坚持使用交换操作N
将1
每个元素放在它的位置上,但这不是一个好主意。
这将是最佳的:
Find element 2
If it is not at correct place already
Find element at position 2
If swapping that with 2 puts both to right place
Swap them
Cost = Cost + min(2, other swapped element)
repeat
Find element 1
If element 1 is at position 1
Find first element that is in wrong place
If no element found
set sorted true
else
Swap found element with element 1
Cost = Cost + 1
else
Find element that should go to the position where 1 is
Swap found element with element 1
Cost = Cost + 1
until sorted is true
如果查找是微不足道的,那么最小交换次数将由周期数决定。它将遵循类似于Cuckoo Hashing的原则。您取排列中的第一个值,然后查看原始索引处的值的索引处的值。如果这些匹配,则交换单个操作。
[ 3 2 1] :值 3 在索引 1 处,因此查看索引 3 处的值。
[3 2 1 ] :值 1 在索引 3 处,因此存在两个索引循环。交换这些值。
如果不是,则将第一个索引压入堆栈并在该索引中查找第二个索引的值。最终会有一个循环。此时,通过从堆栈中弹出值开始交换。这将采用等于 n-1 的交换次数,其中 n 是循环的长度。
[ 3 1 2] :值 3 在索引 1 处,因此查看索引 3 处的值。
[3 1 2 ] :值 2 在索引 3 处,因此将 3 添加到堆栈并查找索引 2。同时存储 3作为循环的起始值。
[3 1 2] :值 1 在索引 2 处,因此将 2 添加到堆栈并查找索引 1。
[ 3 1 2] :值 3 是循环的开始,因此将弹出 2 交换出堆栈并交换值1 和 2。
[1 3 2] :将 3 从堆栈中弹出并交换 2 和 3,从而得到一个包含 2 个交换的排序列表。
[1 2 3]
使用此算法,交换的最大数量将为 N-1,其中 N 是值的总数。当存在 N 个长度的循环时会发生这种情况。
编辑:这个算法给出了最小的交换次数,但不一定是使用 min(x, y) 函数的最小值。我没有计算过,但我相信只有一次不应该使用 swap(x, y) = {swap(1, x), swap(1, y), swap(1, x)}是当 x 在 {2,3} 和 n < 2 时;应该很容易把它写成一个特例。可能最好明确检查并放置 2 和 3,然后按照评论中提到的算法在两个操作中实现排序。
编辑2:很确定这将涵盖所有情况。
while ( unsorted ) {
while ( 1 != index(1) )
swap (1 , index (1) )
if (index(2) == value@(2))
swap (2, value@(2) )
else
swap (1 , highest value out of place)
}
如果您有数字 1, 2, ..., N的排列,那么排序后的集合将恰好是 1, 2, ..., N。所以你知道复杂度为 O(0) 的答案(即你根本不需要算法)。
如果你真的想通过重复交换对范围进行排序,你可以重复“前进和循环”:在已经排序的范围(where )上前进a[i] == i
,然后交换直到完成循环。重复直到你到达终点。这最多需要N - 1 次交换,并且它基本上执行置换的循环分解。a[i]
a[a[i]]
唔。一个有趣的问题。我想到的一个快速算法是使用元素作为索引。我们首先找到一个值为 1 的元素的索引,并将其与该数字的元素交换。最终这将导致 1 出现在第一个位置,这意味着您必须将 1 与一些尚未在该位置的元素交换,然后继续。最高为 2*N-2,下限为 N-1,用于排列 (2,3,...,N,1),但具体成本会有所不同。
好的,鉴于上面的算法和示例,我认为最好的方法是用任何东西交换 1 直到它首先达到第一名,然后如果它还没有到位,则用第二名交换 2,然后继续用任何东西交换 1 还没有到位,直到排序。
set sorted=false
while (!sorted) {
if (element 1 is in place) {
if (element 2 is in place) {
find any element NOT in place
if (no element found) sorted=true
else {
swap 1 with element found
cost++
}
} else {
swap 2 with element at second place
cost+=2
}
} else {
find element with number equals to position of element 1
swap 1 with element found
cost++
}
}
使用桶大小为 1
的桶排序。成本为零,因为没有交换发生。现在通过存储桶数组,并将每个值交换回原始数组中的相应位置。
那是N次交换。
N 的总和为 N(N+1)/2,为您提供准确的固定成本。
一种不同的解释是,您只需从存储桶数组中存储,回到原始数组中。那是没有掉期,因此成本为零,这是一个合理的最小值。