你給出的數字1, 2, ... ,n
列表 - 有n!-1
swap
操作,將產生的列表,其中swap (i, j)
掉在細胞i
和j
要素的所有n!
排列的順序?當輸入列表未被排序爲開始和/或列表中有重複時,一般情況如何?是否有一系列交換會產生所有可能的排列?
上下文:我正在解決一個問題,如果你已經知道2個元素被交換的分數,並且我想暴力(使用C++ next_permutation()
)所有可能的排列,那麼數組的「分數」很容易計算。
你給出的數字1, 2, ... ,n
列表 - 有n!-1
swap
操作,將產生的列表,其中swap (i, j)
掉在細胞i
和j
要素的所有n!
排列的順序?當輸入列表未被排序爲開始和/或列表中有重複時,一般情況如何?是否有一系列交換會產生所有可能的排列?
上下文:我正在解決一個問題,如果你已經知道2個元素被交換的分數,並且我想暴力(使用C++ next_permutation()
)所有可能的排列,那麼數組的「分數」很容易計算。
當然,這是17世紀的鐘聲鈴聲。那麼對於一些組合歷史來說如何?
請參閱the Steinhaus Johnson Trotter algorithm或諮詢您當地的變化小組。
我對你的問題的第二部分做了一些研究,也就是說是否可以用重複元素做到這一點。我相信答案是「是的,但不是那麼容易」。此外,不可能用僅有相鄰交換的重複元素對列表進行排列,因爲可以容易地看到集合{0, 0, 1, 1}
。然而,只有單一掉期纔有可能。
基本的方法是使用基本的變化振鈴算法,但在相同元素的組而不是單個元素上。對於一組k
相同的元素,您需要能夠使用列表組合的算法(其中n是基本集合的總大小)。有很多這樣的算法存在,但我找不到任何真正簡單的算法;最簡單的方法是(粗略地說)爲整個組指定一個方向,並且還指向每個1
(以與Shimon Even算法類似的方式)。當移動組時,最左邊的元素來回掃描;每次它改變方向時,右邊的下一個移動元素就會執行一個;等等。這最終將整個組從右側列表移動到左側,在此之後,其整體方向被翻轉並且返回到原始配置,現在以最右邊的元素領先掃描。
由於在這種情況下方向反轉的次數可能是偶數,所以上述算法可能無法找出置換週期,但我相信可以使用更復雜的算法產生一個週期。實際上,你正在尋找一個由每個置換可能的單次交換誘發的哈密爾頓循環 - 一個變形的置換體 - 但是,儘管存在哈密爾頓循環,但它們並不是很容易找到,因爲圖是相當大。
@MitchWheat:這個問題可以清楚多少? OP要求一個算法(如果存在的話)用於生成next_permutation(與std :: next_permutation不同),在每次調用時只進行一次交換。 – rici
我很困惑,爲什麼這不是一個真正的問題 - 我是否在錯誤的地方問這個問題? @mitchWheat - 我嘗試了谷歌搜索,如果這就是你問 - 不知道我所嘗試的是相關的。 – pathikrit