|
|
1
16
我认为应该这样做:
注意:这是Java。如果在没有垃圾收集的语言中执行此操作,请确保删除
如果您关心空间,可以使用位集
此算法复制t n+k次的实例,其中k是排列中的循环数。您可以通过跳过p[i]=i的那些i,将其减少到最佳的拷贝数。 |
|
|
2
7
方法是遵循排列的“排列周期”,而不是从左到右索引数组。但是,由于必须从某个地方开始,每当需要新的排列周期时,搜索未经授权的元素都是从左到右的: // Pseudo-code N : integer, N > 0 // N is the number of elements swaps : integer [0..N] data[N] : array of object permute[N] : array of integer [-1..N] denoting permutation (used element is -1) next_scan_start : integer; |
|
|
3
7
你的意思是你有一个对象数组o[1..n]然后你有一个数组p[1..n]包含数字1..n的排列,最后你想得到一个对象数组o1,使得所有k=1..n的o1[k]=o[p[k]]? 例如,如果您的对象是字母a、b、c…、y、z,并且您的数组p是[26、25、24、…、2、1]那么您想要的输出是z、y…、c、b、a吗? 如果是的话,我相信你可以用0(1)个额外的内存在线性时间内完成它。数组的反转元素是这种情况下的一种特殊情况。一般来说,我认为您需要考虑将置换p分解成循环,然后使用它来移动原始数组o[]的元素。 如果这就是你要找的,我可以详细说明。 编辑:其他人在我睡觉的时候已经提出了很好的解决方案,所以不需要在这里重复。^ ^ ^ 编辑:我的O(1)附加空间确实不完全正确。我只考虑“数据”元素,但实际上,每个排列元素还需要存储一个位,所以如果我们是精确的,就需要额外的O(log n)位。但大多数时候使用符号位(如J.F.Sebastian所建议的)是很好的,所以在实践中我们可能不需要比我们已经拥有的更多的东西。 |
|
|
4
1
如果您不介意为额外的索引散列分配内存,那么可以保留原始位置到当前位置的映射,以获得接近o(n)的时间复杂性。这是Ruby中的一个例子,因为它是可读和伪代码的。(这可能比较短,也可能更惯用红宝石色,但为了清晰起见,我已经把它写了出来。)
这显然需要一些额外的散列内存,但是因为它只是用于索引,而不是用于“相当大”的对象,希望这是可以接受的。因为散列查询是O(1),即使由于一个项目被交换了不止一次,并且您必须重写的情况,复杂性也会略有增加。
如果你想的话,你可以提前建立一个从原始到当前位置的完整哈希,或者保持从当前到原始的反向哈希,并稍微修改算法,使其严格降到O(N)。它会更复杂一些,占用更多的空间,所以这是我写的版本,但是修改不应该很困难。 编辑:事实上,我相当确定时间复杂性只是O(N),因为每个顺序最多可以有一个关联的跃点,因此查找的最大数量限制为N。 |
|
|
5
1
算法(正如我在写它之后注意到的)与 @meriton's answer in Java .
这里有一个
|
|
|
6
0
有一个 histogram sort 尽管运行时间比O(n)(n日志n)高一点。 |
|
7
0
我可以在有O(N)划痕空间的情况下完成它——复制到新数组并复制回。 编辑:我知道将要进行的算法的存在。其思想是在1..n整数数组上执行交换,同时在大型对象数组上镜像交换。我现在找不到算法。 |
|
|
8
0
这个问题是在有最小O(1)额外存储的地方应用置换的问题之一:“原位置换”。 它 是 可解,但算法事先并不明显。 它被简单地描述为Knuth中的一个练习,对于工作,我必须破译它并弄清楚它是如何工作的。看5.2 13。 关于这个问题的一些更现代的研究,使用伪代码: |
|
|
9
0
我最后为这个编写了一个不同的算法,它首先生成一个交换列表来应用一个订单,然后运行整个交换来应用它。其优点是,如果要对多个列表应用排序,则可以重用交换列表,因为交换算法非常简单。
|
|
|
feasega · 聚合物模拟-2个节点之间的最短路线,适用于所有节点 1 年前 |
|
|
Alisa Petrova · 在有向图中更改一对顶点以创建循环 1 年前 |
|
|
b39b332d · 使用C++标准库实现高效间隔存储 1 年前 |
|
ABGR · 二叉树的直径——当最长路径不通过根时的失败案例 1 年前 |
|
|
EpicAshman · 数独棋盘程序中同一列和同一行出现两次的数字 1 年前 |