1. 程式人生 > >求字串的所有組合數(分冶法+遞迴)c++程式碼實現

求字串的所有組合數(分冶法+遞迴)c++程式碼實現

題目:輸入一個字串,求字元的所有組合。例如輸入字串abc,則它的組合有a、b、c、ab、ac、bc、abc。

當交換字串中的兩個字元時,雖然能得到兩個不同的排列,但卻是同一組合。

下面假設字串中所有字元都不相同。如果輸入n個字元,則這n個字元能構成長度為1的組合、長度為2的組合、。。長度為n的組合。在求n個字元的長為m(1<=m<=n)的組合的時候,採用分冶法的思想,將大問題分解成小問題,然後再用遞迴地解決這些小問題。本題採取的思路是:把這n個字元分成兩部分:第一個字元和其餘的所有字元。若把第一個字元放進組合裡,則下一步在剩餘的字元裡選取m-1個字元。若不把第一個字元放進組合裡,則下一步在剩餘的n-1個字元裡選取m個字元。這就相當於把求n個字元組成長度為m的組合的問題分解成兩個子問題,分別求n-1個字串中長為m-1的組合以及求n-1個字串中長為m的組合。這兩個子問題都可以用遞迴地方式解決。

程式碼如下:

#include <iostream>
#include <stdio.h>
#include <vector>
using namespace std;

void combination(char* ptr, int n, vector<char> &result);

void combination(char* ptr)
{
	if (ptr == NULL)
		return;

	vector<char> result;
	int i, length = strlen(ptr);
	for (i = 1; i <= length; ++i)
	{
		combination(ptr, i, result);
	}
}

void combination(char* ptr, int n, vector<char> &result)
{
	if (ptr == NULL)
		return;

	if (n == 0)
	{
		vector<char>::iterator iter = result.begin();
		for (; iter != result.end(); ++iter)
		{
			cout << *iter;
		}
		cout << endl;
		return;
	}

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

	result.push_back(*ptr);
	combination(ptr + 1, n - 1, result); //若把第一個字元放到組合中去,則需要在剩下的n-1個字元中選取m-1個字元。
	result.pop_back(); //彈出容器的頂層元素
	combination(ptr + 1, n, result);
}


int main()
{
	char ptr[] = "abc"; 
	combination(ptr);
	system("pause");
	return 0;
}