給定數字 1、2、3、4,組成互不相同且無重複數字的三位數。求總個數並列出所有數字。核心考點:三重循環枚舉、去重條件判斷、排列數學公式驗證。
#include <stdio.h>
int main() {
int i, j, k;
int count = 0;
int results[100]; // 足夠大
for (i = 1; i <= 4; i++) { // 百位
for (j = 1; j <= 4; j++) { // 十位
if (i == j) continue; // 百位≠十位
for (k = 1; k <= 4; k++) { // 個位
if (k == i || k == j) continue; // 個位≠百位且≠十位
results[count++] = i * 100 + j * 10 + k;
}
}
}
printf("共有 %d 個互不相同無重複的三位數:\n", count);
for (i = 0; i < count; i++) {
printf("%d ", results[i]);
if ((i + 1) % 8 == 0) printf("\n"); // 8個換行
}
printf("\n");
return 0;
}
從 4 個不同元素中取 3 個有序排列:P(n,k) = n!/(n-k)!。程序輸出應為 24 個。
123 124 132 134 142 143 213 214 231 234 241 243 312 314 321 324 341 342 412 413 421 423 431 432 共 24 個
| 方案 | 時間複雜度 | 空間 | 特點 |
|---|---|---|---|
| 三重循環過濾 (原版) | O(n³) = 64 次迭代 | O(k) | 直觀、易理解、常數小 |
| 遞歸回溯 (通用全排列) | O(P(n,k)) = 24 次遞歸 | O(k) 棧 | 無冗餘迭代、通用性強 |
| next_permutation (C++ STL) | O(k!) 排序 + O(k) 生成 | O(1) | C++ 首選、字典序生成 |
| 位掩碼枚舉 | O(2^n) = 16 狀態 | O(1) | 位運算技巧、適合 n≤32 |
void permute(int *nums, int n, int *used, int *path, int depth, int k) {
if (depth == k) {
// 輸出 path[0..k-1]
return;
}
for (int i = 0; i < n; i++) {
if (!used[i]) {
used[i] = 1;
path[depth] = nums[i];
permute(nums, n, used, path, depth + 1, k);
used[i] = 0;
}
}
}
// 調用
int nums[] = {1,2,3,4};
int used[4] = {0}, path[3];
permute(nums, 4, used, path, 0, 3);
for (int mask = 0; mask < (1<<4); mask++) {
if (__builtin_popcount(mask) != 3) continue; // 僅3個位元為1
int digits[3], idx = 0;
for (int i = 0; i < 4; i++)
if (mask & (1<
int count_unique_numbers(int *digits, int n, int k, int **out) {
// 動態分配結果數組,最大 P(n,k)
int max = 1;
for (int i = 0; i < k; i++) max *= (n - i);
*out = malloc(max * sizeof(int));
// 回溯生成...
return actual_count;
}
無重複三位數枚舉是「排列生成、條件過濾、數學驗證」的基礎練習。關鍵收穫:
P(n,k) 是檢查結果正確性的金標準;__builtin_popcount) 是位運算愛好者的優雅技巧;next_permutation 為首選,C 語言需手寫回溯或引入庫。