# 组合算法面试题

## 一、求一个集合的全部子集

void Combination(char* string)
{
if(string == NULL)
return;
int length = strlen(string);
vector<char> result;
for(int i = 1; i <= length; ++ i)
{
Combination(string, i, result); //从strng中选择i个字符，结果保存在result中
}
}

void Combination(char* string, int number, vector<char>& result)
{
if(number == 0)
{
vector<char>::iterator iter = result.begin();
for(; iter < result.end(); ++ iter)
printf("%c", *iter);
printf("\n");
return;
}

if(*string == '\0')
return;

result.push_back(*string); //选择当前字符
Combination(string + 1, number - 1, result);
result.pop_back();  //不选当前字符
Combination(string + 1, number, result);
}

001           a

010           b

011           a       b

...

void comb(char *str) {
int len = strlen(str); //字符串长度，如str = “abc”长度为3
int max = 1 << len; //字符串自己的数目，如"abc"子集数目为8
for (int i=1; i<max; i++) {  //输出所有子集，这里除去空集，所以从i=1开始输出
int k = i;
int index = 0;
while (k > 0) {
if (k & 1) {
cout << str[index] << " ";
}
k >>= 1;
index++;
}
cout << endl; //每次输出一个子集换行
}
}


## 二、人民币问题

/*
* rmb.cpp
*
*  Created on: 2012-8-28
*      Author: shusheng
*/

#include <iostream>
using namespace std;

#define N 6

int w[N];
int number_used[N];
bool is_used[N];
int countnum = 0;

void init()
{
w[0] = 1;
w[1] = 2;
w[2] = 5;
w[3] = 10;
w[4] = 20;
w[5] = 50;
for (int i = 0; i < N; i++) {
number_used[i] = 0;
}
}

void rmb(int start_index, int left_weight)
{
if (left_weight == 0) {
for (int i = 0; i < N; i++) {
if (number_used[i] > 0)
cout << w[i] << "元: " << number_used[i] << "张 ";
}
cout << endl;
countnum++;
return;
}
for (int i = start_index; i < N; i++) {
if (left_weight >= w[i]) {
number_used[i]++;
rmb(i, left_weight - w[i]);
number_used[i]--;
}
}
}

int main()
{
init();
rmb(0, 100);
cout << countnum << endl;
return 0;
}



void rmb(int start_index, int left_weight)
{
if (left_weight == 0)
{
for (int i = 0; i < N; i++)
{
if (number_used[i] > 0) cout << w[i] << "元: "<< number_used[i] <<"张 ";
}
cout << endl;
return;
}
for (int i = start_index; i < N; i++)
{
int y = left_weight;
while (y >= w[i]) {
number_used[i]++;
y -= w[i];
rmb(i+1, y);
}
number_used[i] = 0;
}
}

## 三、整数分解问题

#include <iostream>
#include <vector>
using namespace std;
#define NUMBER 10  //要分解的数为10
static int cnt = 0; //分解数目
vector<int> part; //用于存储分解结果
void generate_partition(int x, int i, int v[])
{
if (x == 0) {  //输出
cout << ++cnt << ": ";
for (int j=0; j<part.size(); j++) {
cout << part[j] << " ";
}
cout << endl;
return;
}

for (int j=i; j<NUMBER-1; ++j) { //输出逻辑是先输出包含1个v[j]的，然后是2个v[j]的...
int select = v[j];
int c = 0, y=x;
while (y >= select) {
part.push_back(select);
y -= select; c++;
generate_partition(y, j+1, v);
}
while (c--)
part.pop_back();
}
}

int main()
{
int x = NUMBER;
int v[NUMBER-1];
for (int i=0; i<NUMBER-1; i++)
v[i] = i+1;
generate_partition(x, 0, v);
return 1;
}