字符串的全排列问题还是一个相当值得思考的问题。
递归方式的全排列很容易想到,但是递归要考虑是否会出现相同字符的时候。
出现相同字符,就不交换。
#include<iostream>
using namespace std;
#include<assert.h>
//在[nBegin,nEnd)区间中是否有字符与下标为pEnd的字符相等
bool IsSwap(char* pBegin , char* pEnd)
{
char *p;
for(p = pBegin ; p < pEnd ; p++)
{
if(*p == *pEnd)
return false;
}
return true;
}
void Permutation(char* pStr , char *pBegin)
{
assert(pStr);
if(*pBegin == '\0')
{
static int num = 1; //局部静态变量,用来统计全排列的个数
printf("第%d个排列\t%s\n",num++,pStr);
}
else
{
for(char *pCh = pBegin; *pCh != '\0'; pCh++) //第pBegin个数分别与它后面的数字交换就能得到新的排列
{
if(IsSwap(pBegin , pCh))
{
swap(*pBegin , *pCh);
Permutation(pStr , pBegin + 1);
swap(*pBegin , *pCh);
}
}
}
}
int main(void)
{
char str[] = "baa";
Permutation(str , str);
return 0;
}
非递归方式找到第一个前面字符比后面字符小的,交换前面那个小的字符和后面刚好比它大一点的字符
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
#include<assert.h>
//反转区间
void Reverse(char* pBegin , char* pEnd)
{
while(pBegin < pEnd)
swap(*pBegin++ , *pEnd--);
}
//下一个排列
bool Next_permutation(char a[])
{
assert(a);
char *p , *q , *pFind;
char *pEnd = a + strlen(a) - 1;
if(a == pEnd)
return false;
p = pEnd;
while(p != a)
{
q = p;
p--;
if(*p < *q) //找降序的相邻2数,前一个数即替换数
{
//从后向前找比替换点大的第一个数
pFind = pEnd;
while(*pFind < *p)
--pFind;
swap(*p , *pFind);
//替换点后的数全部反转
Reverse(q , pEnd);
return true;
}
}
Reverse(a , pEnd); //如果没有下一个排列,全部反转后返回false
return false;
}
int cmp(const void *a,const void *b)
{
return int(*(char *)a - *(char *)b);
}
int main(void)
{
char str[] = "bac";
int num = 1;
qsort(str , strlen(str),sizeof(char),cmp);
do
{
printf("第%d个排列\t%s\n",num++,str);
}while(Next_permutation(str));
return 0;
}
八皇后问题用字符串的全排列竟然也可以解决!
#include<iostream>
using namespace std;
int g_number = 0;
void Permutation(int * , int , int );
void Print(int * , int );
void EightQueen( )
{
const int queens = 8;
int ColumnIndex[queens];
for(int i = 0 ; i < queens ; ++i)
ColumnIndex[i] = i; //初始化
Permutation(ColumnIndex , queens , 0);
}
bool Check(int ColumnIndex[] , int length)
{
int i,j;
for(i = 0 ; i < length; ++i)
{
for(j = i + 1 ; j < length; ++j)
{
if( i - j == ColumnIndex[i] - ColumnIndex[j] || j - i == ColumnIndex[i] - ColumnIndex[j]) //在正、副对角线上
return false;
}
}
return true;
}
void Permutation(int ColumnIndex[] , int length , int index)
{
if(index == length)
{
if( Check(ColumnIndex , length) ) //检测棋盘当前的状态是否合法
{
++g_number;
Print(ColumnIndex , length);
}
}
else
{
for(int i = index ; i < length; ++i) //全排列
{
swap(ColumnIndex[index] , ColumnIndex[i]);
Permutation(ColumnIndex , length , index + 1);
swap(ColumnIndex[index] , ColumnIndex[i]);
}
}
}
void Print(int ColumnIndex[] , int length)
{
printf("%d\n",g_number);
for(int i = 0 ; i < length; ++i)
printf("%d ",ColumnIndex[i]);
printf("\n");
}
int main(void)
{
EightQueen();
return 0;
}
在[1,....,n]数中找到和为sum的序列
vector<int> r;
void f(int sum,int n)
{
if(sum==0)
{
//find
}
if(n==0) return;
if(n*(n+1)/2<sum)return;
r.push_back(n);
f(sum-n,n-1);
r.pop_back();
f(sum,n-1);
}
http://blog.youkuaiyun.com/hackbuteer1/article/details/7462447