2012-04-12 44 views
1

我在互聯網上搜索了很多如何做到這一點,但我沒有想出一些我完全理解的東西。從字母組獲取文字組合

進出口試圖通過指定的信量來計算每個組中,例如,以產生從字母陣列中的所有可能的組合:

字母:A, B, C

長度:2

結果: AB, AC, BC

(我知道有:BA,CACB太,但我只需要得到該組的順序沒關係)

例子2:

字母:A, B, C, D

長度:3

結果:ABC, ACD, BCD, CDA, DAB

等..

我打算在C++中實現該算法,但C#,Java或Javascript中的示例是welc ome也是如此。

+0

似乎相當密切相關[這個問題](http://stackoverflow.com/questions/361/產生 - - 的 - 所有可能的 - 排列對的一字符串列表)。 – Geoff 2012-04-12 15:35:57

+0

生成部分組可能更容易,如果您在內部始終按升序生成它們,如:'abc','acd','bcd','acd','abd'...並按abc,abd ,acd - 啊,你有兩次!看到! – 2012-04-12 15:37:44

+0

下面是一個Python實現:http://docs.python.org/library/itertools.html#itertools。組合 – 2012-04-12 15:48:17

回答

1

如果你在一個可再現的方式進行訂購,你會發現一個算法更容易產生他們:

讓我們把它不太容易,拿3分:

e d c b a 
--------- 
    x x x abc 
    x x x abd 
x  x x abe 
    x x x acd 
x x x ace 
x x  x ade 
    x x x bcd 
x x x bce 
x x x bde 
x x x  cde 
+0

謝謝!這非常有幫助! – UnTraDe 2012-05-31 12:31:39

1

似乎很適合遞歸。取每個元素,並將其添加到其餘的組合中,直到滿足給定的深度。

static List<String> func(List<String> a, Int32 depth) 
{ 
    List<String> retVal = new List<String>(); 
    if (depth <= 0) 
    { 
     return retVal; 
    } 
    for (int i = 0; i < a.Count; i++) 
    { 
     String element = a[i]; 

     List<String> temp = new List<String>(a); 
     temp.RemoveAt(i); 
     List<String> resultset = func(temp, depth - 1); 
     if (resultset.Count == 0) 
     { 
      retVal.Add(element); 
     } 
     else 
     { 

      foreach (String result in resultset) 
      { 
       retVal.Add(element + result); 
      } 
     } 
    } 
    return retVal; 
} 
0

這應該工作,如果你稍微調整它:

void r_nCr(const unsigned int &startNum, const unsigned int &bitVal, const unsigned int &testNum) // Should be called with arguments (2^r)-1, 2^(r-1), 2^(n-1) 
{ 
    unsigned int n = (startNum - bitVal) << 1; 
    n += bitVal ? 1 : 0; 

    for (unsigned int i = log2(testNum) + 1; i > 0; i--) // Prints combination as a series of 1s and 0s 
     cout << (n >> (i - 1) & 1); 
    cout << endl; 

    if (!(n & testNum) && n != startNum) 
     r_nCr(n, bitVal, testNum); 

    if (bitVal && bitVal < testNum) 
     r_nCr(startNum, bitVal >> 1, testNum); 
} 

說明here

1

這被稱爲排列,有很多解決方案。 這是一個非遞歸的,我寫的速度非常快。 (如果你在Windows上,你可能需要查找_BitScanReverse而不是__builtin_ctz)。

#include <iostream> 
#include <cstdlib> 
using namespace std; 

void perm(unsigned &v) { //v must be initialised with t = (2 << N) - 1; 
    unsigned t = v | (v - 1); 
    v = (t + 1) | (((~t & -~t) - 1) >> (__builtin_ctz(v) + 1)); 
} 

int main (int argc, char *argv[]) { 
    unsigned n = argc > 1 ? atoi(argv[1]) : 3; //bins: 0..31 
    unsigned k = argc > 2 ? atoi(argv[2]) : 2; //things: 0 .. bins. 
    unsigned m = (1 << n) - 1; //bitmask is size of n (bins). 
    unsigned v = (1 << k) - 1; //start value - initial allocation. 
    do { 
     cout << bitset<31>(v & m) << endl; 
     perm(v); 
    } while (v < m); 
    return 0; 
} 

在你的問題中,你建議 - 字母:A,B,C長度:2爲例。 所以,這個代碼將產生(通過3 2作爲參數)(我曾評論)

ABC 
011 //BC 
101 //AC 
110 //AB