字符串的全排列

字符串的全排列问题还是一个相当值得思考的问题。

递归方式的全排列很容易想到,但是递归要考虑是否会出现相同字符的时候。

出现相同字符,就不交换。

#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.csdn.net/hackbuteer1/article/details/7462447

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值