2012-11-03 74 views
6

你給出的數字1, 2, ... ,n列表 - 有n!-1swap操作,將產生的列表,其中swap (i, j)掉在細胞ij要素的所有n!排列的順序?當輸入列表未被排序爲開始和/或列表中有重複時,一般情況如何?是否有一系列交換會產生所有可能的排列?

上下文:我正在解決一個問題,如果你已經知道2個元素被交換的分數,並且我想暴力(使用C++ next_permutation())所有可能的排列,那麼數組的「分數」很容易計算。

+4

@MitchWheat:這個問題可以清楚多少? OP要求一個算法(如果存在的話)用於生成next_permutation(與std :: next_permutation不同),在每次調用時只進行一次交換。 – rici

+1

我很困惑,爲什麼這不是一個真正的問題 - 我是否在錯誤的地方問這個問題? @mitchWheat - 我嘗試了谷歌搜索,如果這就是你問 - 不知道我所嘗試的是相關的。 – pathikrit

回答

15

當然,這是17世紀的鐘聲鈴聲。那麼對於一些組合歷史來說如何?

請參閱the Steinhaus Johnson Trotter algorithm或諮詢您當地的變化小組。


我對你的問題的第二部分做了一些研究,也就是說是否可以用重複元素做到這一點。我相信答案是「是的,但不是那麼容易」。此外,不可能用僅有相鄰交換的重複元素對列表進行排列,因爲可以容易地看到集合{0, 0, 1, 1}。然而,只有單一掉期纔有可能。

基本的方法是使用基本的變化振鈴算法,但在相同元素的組而不是單個元素上。對於一組k相同的元素,您需要能夠使用列表組合的算法(其中n是基本集合的總大小)。有很多這樣的算法存在,但我找不到任何真正簡單的算法;最簡單的方法是(粗略地說)爲整個組指定一個方向,並且還指向每個1(以與Shimon Even算法類似的方式)。當移動組時,最左邊的元素來回掃描;每次它改變方向時,右邊的下一個移動元素就會執行一個;等等。這最終將整個組從右側列表移動到左側,在此之後,其整體方向被翻轉並且返回到原始配置,現在以最右邊的元素領先掃描。

由於在這種情況下方向反轉的次數可能是偶數,所以上述算法可能無法找出置換週期,但我相信可以使用更復雜的算法產生一個週期。實際上,你正在尋找一個由每個置換可能的單次交換誘發的哈密爾頓循環 - 一個變形的置換體 - 但是,儘管存在哈密爾頓循環,但它們並不是很容易找到,因爲圖是相當大。

+0

我查看了維基百科頁面的鏈接,但我並不理解這一行:「在每一步之後,所有大於所選元素的元素都將其方向設置爲正值或負值,這取決於它們是集中在開始還是結束的排列分別。「在這種情況下,「集中」意味着什麼? – pathikrit

+0

集中==集羣或集羣。有問題的元素(大於所選元素)在排列的開始和結束處聚集在一起。也就是說,對於任何大於所選元素的元素,要麼不存在不大於所選元素的元素,要麼不存在不大於所選元素的元素。 – rici

+0

謝謝,我得到了一個可用的Java版本 - 它非常整齊,因爲不僅每個排列都與下一個交換不同 - 而且還有**相鄰的交換,甚至更好! – pathikrit