#include <iostream>
#include <algorithm>
using namespace std;
typedef string::iterator StringItr;
void itr_swap(StringItr i, StringItr j)
{
char tmp = *i;
*i = *j;
*j = tmp;
}
void reverse(StringItr i, StringItr j) {
while (i < j) {
itr_swap(i, j);
++i, --j;
}
}
bool next(string& str)
{
StringItr start = str.begin();
StringItr end = str.end() - 1;
if(start == end) {
return false;
}
StringItr i = start;
++i;
if (i == end)
return false;
i = end;
while(true) {
StringItr t = i;
--i;
if (*i < *t) {
StringItr j = end;
while(!(*i < *j))
j--;
itr_swap(i, j);
reverse(t, end);
return true;
}
if (i == start) {
//all reverse, generate min dictionary
reverse(start, end);
return false;
}
}
}
void permutation(string& str)
{
if (str.empty())
return;
StringItr start = str.begin();
StringItr end = str.end();
sort(start, end);
do{
cout << ">>" << str << endl;
}while(next(str));
}
int main(int argc, char *argv[])
{
if (argc == 2) {
string str(argv[1]);
permutation(str);
} else {
string str = "bac";
permutation(str);
}
}
组合
递归方法
思路描述
- 对每一个字符而言,可以选择将其加入组合中,也可以选择不将其加入组合中:
- 若选择加入组合,则从后N-1个字符中,选择m-1个字符加入到组合中
- 若不选择加入组合,则从后N-1个字符中,选择m个字符加入到组合中
算法实现
#include <iostream>
using namespace std;
typedef string::iterator StringItr;
void _combination(string& str, StringItr current, int m, char *b, int index)
{
if (current == str.end())
return;
//don't choose current pos
_combination(str, current+1, m, b, index);
//choose current pos
b[++index] = *current;
_combination(str, current+1, m, b, index);
if (index == (m-1)) {
b[m] = '\0';
cout << b << endl;
}
}
void combination(string& str)
{
char b[str.size() + 1];
for (int i = 1; i < str.size(); i++ ) {
_combination(str, str.begin(), i, b, -1);
}
}
int main(int argc, char *argv[])
{
if (argc == 2) {
string str(argv[1]);
combination(str);
} else {
string str = "abc";
combination(str);
}
return 0;
}
迭代方法-01法
思路描述
- 展开一个数组,其下标表示1~N个数,数组元素的值为1表示其代表的数被选中,为0表示没被选中。
- 初始化:将数组前M个元素置1,表示第一个组合为前M个数
- 然后从左到右扫描数组元素值为“10”组合,找到第一个“10”组合后将其变为01组合,同时将左边所有的“1”全部移动到数组的最左端。
- 当第一个1移动到数组的n-m的位置时,M个1全部移动到最右端,就得到了最后一个组合
算法实现
#include <iostream>
using namespace std;
void print_result(string& str, int *loc)
{
int length = str.size();
for (int i = 0; i < length; i++) {
if (loc[i])
cout << str[i];
}
cout << endl;
}
int first_1_pos(int *loc, int length)
{
for (int i = 0; i < length; i++) {
if(loc[i]) {
return i;
}
}
return -1;
}
int first_10_pos(int *loc, int length)
{
for (int i = 0; i < length - 1; i++) {
if(loc[i] && loc[i+1] == 0) {
return i;
}
}
return -1;
}
void swap(int &a, int &b)
{
a = b + a;
b = a - b;
a = a - b;
}
void move_1_to_left(int *loc, int end)
{
for (int old = 0, pos = 0; old < end; old++) {
if (loc[old] && pos != old) {
loc[pos++] = 1;
loc[old] = 0;
}
}
}
void _combination(string& str, int *loc, int m)
{
//initialize loc array
int length = str.size();
for (int i = 0; i < length; i++) {
if (i < m)
loc[i] = 1;
else
loc[i] = 0;
}
print_result(str, loc);
int first_1 = first_1_pos(loc, length);
int end_condition = length - m;
//loop to search all m combinations
while (first_1 != end_condition) {
int first_10 = first_10_pos(loc, length);
swap(loc[first_10], loc[first_10+1]);
move_1_to_left(loc, first_10);
print_result(str, loc);
first_1 = first_1_pos(loc, length);
}
}
void combination(string& str)
{
int length = str.size();
int loc[length];
for (int i = 1; i < length; i++) {
_combination(str, loc, i);
}
}
int main(int argc, char *argv[])
{
if (argc == 2) {
string str(argv[1]);
combination(str);
} else {
string str = "abc";
combination(str);
}
return 0;
}