求解幂级问题
问题描述:
对于给定的正整数n(n>=1),求1~n构成的集合的幂集(即由1 ~ n的集合中所有子集构成的集合,包括空集合全集)
- 思路一:穷举法
时间复杂度:O(n × 2^n)
f()的时间为O(n)
将1 ~ n存放到数组a中,求解问题变为构造集合a的所有子集合。
设集合a[0 … 2]={1,2,3},其所有集合元素对应的二进制及其十进制
对于含n(n>=1)个元素的集合a,求解幂集过程如下:
for(i=0;i<2^n;i++){
将i转换为二进制数b;
输出b中为1的位对应的a元素构成一个集合元素
}
代码1:
#include<stdio.h>
#include<math.h>
#define MaxN 10
void f(int b[],int n){ //b表示二进制数增1
for(int i=0;i<n;i++){ //遍历数组b
if(b[i])
b[i]=0; //将元素1改为0
else
{
b[i]=1; //将元素0改为1
break;
}
}
}
void Pset(int a[],int b[],int n){
int i,k;
int pw=(int)pow(2,n); //2^n
printf("1~%d 的幂集:\n",n);
for(i=0;i<pw;i++){ //执行2^n
printf("{");
for(k=0;k<n;k++)
if(b[k])
printf("%d ",a[k]);
printf("}");
f(b,n);
}
printf("\n");
}
int main(){
int n=3;
int a[MaxN],b[MaxN];
for(int i=0;i<n;i++){
a[i]=i+1; //a初始化为{1,2,3}
b[i]=0; //b初始化为{0,0,0}
}
Pset(a,b,n);
}
- 思路二:增量穷举法
n=3时,求解过程
(1)产生一个空集元素{} 添加到ps中,即ps={ {} }
(2)在步骤1得到的ps的每一个集合元素的末尾添加1构成新集合元素{1},将其添加到ps中,即ps={ {} 、{1}}
(3)在步骤2得到的ps的每一个集合元素的末尾添加1构成新集合元素{2},将其添加到ps中,即ps={ {} 、{1}、{2}、{1,2}}
(4)依次这样
最后ps构成{1、2、3}的幂集
在实现算法时用一个vector< int >容器表示一个集合元素,vector<vector < int > >存放幂集
代码2:
#include<stdio.h>
#include<vector>
using namespace std;
vector<vector<int >> ps; //存放幂集
void Pset(int n){
vector<vector<int >> ps1; //子幂集
vector<vector<int >>::interator it; //幂集迭代器
vector<int > s;
ps.push_back(s); //添加{}空集合元素
for(int i=1;i<=n;i++){
ps1=ps; //ps1存放上一步得到的幂集
for(it=ps1.begin();it!=ps1.end();it++)
(*it).push_back(i); //在ps每个集合元素的末尾添加i
for(it=ps1.begin();it!=ps1.end();it++)
ps.push_back(*it); //将ps1的每个集合元素添加到ps中
}
}
void disp(){
vector<vector<int >>::interator it;
vectorr<int >::interator sit;
for(it=ps1.begin();it!=ps.end();++it)
{
printf("{");
for(sit=(*it).begin();sit!=(*it).end();++sit)
printf("%d ",*sit);
printf("}");
}
printf("\n");
}
int main(){
int n=3;
Pset(n);
printf("1 ~ %d 的幂集:\n",n);
disp();
}