給定一個字符串,生成其所有非空子集組合(保持原序)。例如 "abc" 的組合為 a, b, c, ab, ac, bc, abc。本質上等價於對長度 n 的二進制數從 1 遍歷到 2^n - 1,每個比特位 1 表示選擇對應字符。本文給出基於位運算的簡潔 C++ 實現。
n,共 2^n - 1 個非空子集。i (1 ≤ i < 2^n) 的二進制表示直接對應選擇方案:第 k 位為 1 選擇 s[k]。i & 1 判斷最低位,i >>= 1 右移遍歷各位。#include <iostream>
#include <vector>
#include <string>
#include <cmath>
using namespace std;
// 根據掩碼 i 生成對應子序列
string BinaryString(const string& s, int i) {
string res;
int k = 0;
while (i) {
if (i & 1) res.push_back(s[k]);
++k;
i >>= 1;
}
return res;
}
// 生成所有非空組合
vector<string> Combination(const string& s) {
vector<string> res;
if (s.empty()) return res;
int total = 1 << s.length(); // 2^n
for (int i = 1; i < total; ++i) { // 從 1 開始,排除空集
res.push_back(BinaryString(s, i));
}
return res;
}
int main() {
string s = "abc";
vector<string> comb = Combination(s);
for (const auto& str : comb) {
cout << str << ' ';
}
cout << endl;
return 0;
}
a b ab c ac bc abc
__builtin_popcount(i) == k 判斷。next_permutation,本質不同。for (int i=1; i 等片段顯然是編輯遺留的亂碼,正確循環條件為 i < total。 pow(2.0, n) 返回 double,大 n 時精度丟失,應用移位 1 << n(n ≤ 30/62)。位運算法以其代碼極簡、無遞歸開銷、易於並行化的優勢,成為生成組合/子集的首選基礎算法。理解「集合與二進制數一一對應」的核心映射,能靈活應對各類組合枚舉問題。