【问题标题】:Is there a sequence of swaps that would generate all possible permutations? [closed]是否有一系列交换会产生所有可能的排列? [关闭]
【发布时间】:2012-11-03 03:04:01
【问题描述】:

给你一个数字列表1, 2, ... ,n - 是否有一系列n!-1 swap 操作会生成列表的所有n! 排列,其中swap (i, j) 在单元格i 和@ 处交换元素987654327@?当输入列表未排序开始和/或列表中有重复时,一般情况如何?

上下文:我正在解决一个问题,如果您已经知道交换 2 个元素的分数并且我想暴力破解(使用 C++ next_permutation())所有可能的排列,那么数组的“分数”很容易计算。

【问题讨论】:

  • @MitchWheat:这个问题能清楚多少? OP 要求一种算法(如果存在)来生成 next_permutation (与 std::next_permutation 不同)每次调用只进行一次交换。
  • 我很困惑为什么这不是一个真正的问题——我问错地方了吗? @mitchWheat - 如果这就是你要问的,我已经尝试过谷歌搜索 - 不确定我尝试的内容是否相关。

标签: algorithm permutation


【解决方案1】:

当然,17 世纪的敲钟人就知道了。那么对于一些组合历史来说怎么样?

请参阅the Steinhaus Johnson Trotter algorithm 或咨询您当地的更改响铃小组。


我对您问题的第二部分进行了一些研究,即是否可以使用重复的元素来做到这一点。我相信答案是“是的,但不是那么容易”。此外,不可能用仅相邻交换的重复元素来置换列表,这在集合{0, 0, 1, 1} 中很容易看出。但是,只需单次交换即可。

基本方法是使用基本的 change-ringing 算法,但在相同元素的组上而不是在单个元素上。对于一组k 相同的元素,您需要能够对列表 0n-k1k 组合的算法(其中 n 是基数的总大小放)。存在许多这样的算法,但我找不到任何真正简单的算法;最简单的一种是(粗略地说)为整个组分配一个方向,并为每个1 分配一个方向(与 Shimon Even 算法类似)。向左移动组时,最左边的元素来回扫过;每次它改变方向时,下一个向右移动的元素都会向前移动;等等。这最终将整个组从列表的右侧移动到左侧,之后其整体方向被翻转并返回到原始配置,现在最右侧的元素引领扫描。

由于在这种情况下方向反转的数量可能是偶数,因此上述算法可能无法追踪置换循环,但我相信使用更复杂的算法可以产生一个循环。实际上,您正在图中寻找一个哈密顿循环,该哈密顿循环是由每个排列的可能单个交换引起的 - 置换面体的一种变体 - 但是,虽然哈密顿循环确实存在,但它们并不那么容易找到,因为这些图是很大。

【讨论】:

  • 我查看了维基百科页面的链接,我不明白这一行:“在每一步之后,所有大于所选元素的元素都将其方向设置为正或负,取决于它们是否分别集中在排列的开头或结尾。”在这种情况下,“集中”是什么意思?
  • 集中 == 聚集或聚集。有问题的元素(大于所选元素)聚集在排列的开始和结束处。也就是说,对于任何大于所选元素的元素,要么没有不大于左侧所选元素的元素,要么没有不大于右侧所选元素的元素。
  • 谢谢,我得到了一个可以工作的 Java 版本 - 它非常简洁,因为不仅每个排列与下一个排列不同 - 而且 adjacent 排列更好!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-12-11
  • 1970-01-01
  • 2014-02-27
  • 2012-05-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多