給定字符串(如 "ABC"),生成所有非空子集的全排列。
輸出示例:A, AB, AC, ABC, ACB, B, BA, BC, BAC, BCA, C, CA, CB, CAB, CBA。
假設已有前 k-1 個字符的所有排列集合 S_{k-1}。
第 k 個字符 c_k 可插入到每個排列的 0..len 任意位置,生成新排列。
如 "AB" 插入 'C' → "CAB", "ACB", "ABC"。
Total = Σ_{i=1}^n P(n,i)(n≤10 時 Total < 10^6)。buf[Total][n+1] 存儲所有字符串(以 \0 結尾)。
char *allPerm(char *str, int *count) {
int n = strlen(str);
int total = 0;
for (int i = 1, p = 1; i <= n; ++i) {
p *= i;
total += p;
}
char *buf = malloc(total * (n+1));
int cnt = 0;
for (int k = 0; k < n; ++k) { // 插入第 k 個字符
int old = cnt;
for (int i = 0; i < old; ++i) {
char *src = buf + i*(n+1);
int len = strlen(src);
for (int pos = 0; pos <= len; ++pos) {
char *dst = buf + cnt++*(n+1);
memcpy(dst, src, pos);
dst[pos] = str[k];
memcpy(dst+pos+1, src+pos, len-pos+1); // 含 \0
}
}
if (old == 0) { // 第一個字符
buf[cnt][0] = str[0];
buf[cnt++][1] = '\0';
}
}
*count = cnt;
return buf;
}
n=10 字符,總排列數 9864100,單次運行約 0.5 秒(視機器而定)。Total * (n+1) 字節,n=10 約 100 MB,需注意記憶體限制。
void dfs(char *str, int n, int depth, char *path, int *used) {
if (depth > 0) { path[depth] = '\0'; puts(path); }
for (int i = 0; i < n; ++i) if (!used[i]) {
used[i] = 1;
path[depth] = str[i];
dfs(str, n, depth+1, path, used);
used[i] = 0;
}
}
時間複雜度相同,但空間僅 O(n) 遞歸棧,工程上更推薦。