至於其他的答案已經暗示,有兩種主要的方法:1)跟蹤你已經產生(所提出的解決方案在這個類別中可能永遠不會終止),或者2)跟蹤尚未產生的排列(這意味着排列必須是預先產生的,這在需求中是特別不允許的)。這是另一個解決方案,可以保證終止並且不需要預先生成,但可能不符合您的隨機化要求(在這一點上是模糊的)。
總體概述:生成樹以跟蹤生成的內容或剩餘內容。通過遍歷樹中的隨機鏈接「選擇」新的置換,在生成該置換後修剪樹葉,以防止它再次生成。
如果沒有白板來描述這一點,我希望這個描述足以描述我的意思:創建一個「節點」,其中包含字母表中每個字母的其他節點的鏈接。這可以通過使用通用的字母表到節點的地圖來實現,或者如果您的字母表是固定的,您可以創建特定的參考。該節點代表字母表中可用的字母,可用於生成排列的下一個「生成」。通過訪問根節點開始生成置換,從該節點中的可用字母中選擇一個隨機字母,然後遍歷該引用到下一個節點。每次遍歷時,都會爲排列生成一封信。當到達一片葉子(即完全構建一個置換)時,你會回溯到樹上,看看父節點是否有剩餘的可用排列;如果沒有,父節點可以被修剪。
作爲一個實現細節,節點可以存儲那些不可用於生成的字母集合,或者當前仍然可以生成的一組字母。爲了可能減少存儲需求,您還可以允許節點存儲或並附上一個標誌,指示它正在做什麼,以便當節點允許一半以上的字母表存儲迄今爲止產生的字母並切換到使用字母只有少於一半的字母可用時仍然存在。
使用這樣的樹結構限制了可以生成的內容,而無需預先生成所有組合,因爲您不需要預先構建整個樹(它可以構造爲生成排列),而且您保證完成,因爲清除節點(也就是說,你只是遍歷節點的鏈接,當這是一個允許的組合產生非產生的排列)。
然而,我認爲該技術的隨機化有點奇怪,我不認爲每個組合在任何給定時間都可能產生的可能性相同,儘管我沒有真正想過這一點。也可能值得注意的是,即使完整樹不一定是預先生成的,所涉及的開銷可能足以使您預先生成所有排列可能更好。
你能告訴我們空間要求是什麼嗎?您是否有理由相信問題可以通過在Y空間使用小於X來解決(並且仍然保證終止)? – 2008-12-14 20:43:59
您需要更具體地瞭解您需要它的「隨機性」,以及您是否真的需要對整個列表進行排列(所有X^Y條目)。 – ShreevatsaR 2008-12-14 22:35:19