问题描述
对于给定的正整数n(n>=1),求1到n构成的集合的幂集(包括全集和空集)
解法一 直接枚举法
思路
将二进制位与幂集对应起来,n的幂集个数为 2 n 2^n 2n,每一个二进制位代表一个元素。下面以n等于3为例。
集合元素 | 对应的二进制位 | 对应的十进制数 |
---|---|---|
{ } | 000 | - |
{1} | 001 | 1 |
{2} | 010 | 2 |
{1,2} | 011 | 3 |
{3} | 100 | 4 |
{1,3} | 101 | 5 |
{2,3} | 110 | 6 |
{1,2,3} | 111 | 7 |
算法复杂度: O ( n ∗ 2 n ) O(n*2^n) O(n∗2n)
实现
#include<bits/stdc++.h>
using namespace std;
/*
Alogorithm Design
蛮力法
1.直接枚举法求解幂集问题
*/
// 将b表示的二进制加1
// b数组下表从小到大对应从低到高位
int inc(int b[],int n){
for(int i=0;i<n;i++){
if(b[i]) b[i]=0;
else{
b[i] = 1;
break;
}
}
}
void PSet(int a[],int b[],int n){
int pw = (int)pow(2,n);
printf("1到%d的幂集为:\n",n);
for(int i=0;i<pw;i++){
cout << "{";
for(int i=0;i<n;i++){
if(b[i])
printf(" %d ",a[i]);
}
cout << "}";
inc(b,n);
}
cout << endl;
}
int main()
{
int n=3;
int a[10],b[10];
for(int i=0;i<n;i++){
a[i] = i+1;
b[i] = 0;
}
PSet(a,b,n);
return 0;
}
解法二 枚举增量法
思路
从最初的空集开始,往里面加第一个元素,将得到的子幂集与原来的幂集合并,就得到了新的子幂集,然后再重复以上操作。
算法复杂度:
O
(
2
n
)
O(2^n)
O(2n)
实现
#include<bits/stdc++.h>
using namespace std;
vector<vector<int> > PSet; // 全局变量 存放幂集
void PSetSolve(int n){
vector<vector<int> > tmp; // 子幂集
vector<int> v;
PSet.push_back(v);
vector<vector<int> >::iterator pit;
vector<int>::iterator it;
for(int i=1;i<=n;i++){
tmp = PSet;
for(pit=tmp.begin();pit!=tmp.end();pit++){
(*pit).push_back(i);
}
for(pit=tmp.begin();pit!=tmp.end();pit++){
PSet.push_back(*pit);
}
}
}
// 打印幂集
void disp(int n){
printf("1到%d的幂集为:\n",n);
for(int i=0;i<pow(2,n);i++){
vector<int> v = PSet[i];
cout << "{";
for(int j=0;j<v.size();j++)
printf(" %d ",v[j]);
cout << "}";
}
}
int main()
{
int n = 3;
PSetSolve(n);
disp(n);
return 0;
}