字符串全排列和组合算法

打印字符串的全排列

算法的思路:

把一个字符串分成两部分,第一个字符+后面部分所有的字符。这样就能够递归的求解整个过程了:

1.每个字符都做一次首字符
2.当某个字符作为首字符的时候,求后面所有字符的全排列

而这里的求后面所有字符的全排列可以看成递归的子问题

全排列的递归树:

但是这里还有一个问题,那就是字符串中有重复的字符时,这样的算法会增加最后的结果数目。比如说字符串aab,a+ab的全排列,然后交换还是a+ab的全排列。所以会增加结果的数目。解决方案就是:当遇到重复的字符的时候就跳过去,不在进行递归。

所以代码实现:

#include <iostream>
#include <algorithm>
using namespace std;

void getPermutation(char *pStr, char *pBegin);
void Permutation(char *pStr);

void Permutation(char *pStr)
{
	if (pStr == NULL)
	{
		return;
	}
	getPermutation(pStr, pStr);
}

void getPermutation(char *pStr, char *pBegin)
{
	if (*pBegin == ‘\0‘)
	{
		printf("%s\n", pStr);
	}
	else
	{
		for (char *pCh = pBegin; *pCh != ‘\0‘; ++pCh)
		{
			//如果是相同的字符,那么就不用在递归,防止产生多余的字符串结果
			if (*pCh == *pBegin && pCh != pBegin)
				continue;

			swap(*pCh, *pBegin);
			getPermutation(pStr, pBegin + 1);
			swap(*pCh, *pBegin);
		}
	}
}//getPermutation

int main()
{
	char str[] = "aab";
	//这里实参如果是char *str = "abc";是不可行的,因为常量字符串是不能交换的
	Permutation(str);

	return 0;
}

这是C语言版的实现,再看C++版本的实现:

vector<string> Permutation(string str)
{
	vector<string> res;
	if(str.size() == 0)
		return res;

	getPermutation(res, str, 0);

	sort(res.begin(), res.end());
	return res;
}

void getPermutation(vector<string>& res, string& str, int begin)
{
	if(begin == str.size())
	{
		res.push_back(str);
	}
	else
	{
		for(unsigned int i = begin; i < str.size(); i++)
		{
			if(str[i] == str[begin] && i != begin)
				continue;
			swap(str[i], str[begin]);
			getPermutation(res, str, begin + 1);
			swap(str[i], str[begin]);
		}//for
	}
}//getPermutation

  

时间: 2024-12-24 01:51:03

字符串全排列和组合算法的相关文章

C递归版的全排列和组合算法

For example, [1,2,3] have the following permutations: [1,2,3], [1,3,2], [2,1,3], [2,3,1], [3,1,2], and [3,2,1]. 全排列: 从1开始递归,然后对2递归,最后对3递归 顺序是先输出 1 2 3  1 3 2  2 1 3   2  3 1 ............稍微分析一下就出来了 class Solution { private: vector<vector<int>>r

字符串数组全排列——逐个追加组合算法

我们在笔试面试过程中经常会遇到关于排列与组合的问题,其实这些可以通过递归简单的实现,看下面两个例子: (1)关于字符串排列的问题 输入一个字符串,打印出该字符串中字符的所有排列.例如输入字符串abc,则输出由字符a.b.c所能排列出来的所有字符串abc.acb.bac.bca.cab和cba. 可以这样想:固定第一个字符a,求后面两个字符bc的排列.当两个字符bc的排列求好之后,我们把第一个字符a和后面的b交换,得到bac;接着我们固定第一个字符b,求后面两个字符ac的排列.现在是把c放到第一位

《编程之法》1.3字符串的全排列,组合,重复排列,八皇后问题

题目描述:输入一个字符串,打印出该字符串中字符的所有排列,例如输入"abc",输出"abc","acb","bac","bca","cab","cba" 解法一:递归实现 类似于图的深度遍历搜索求全路径的算法,每次交换两个数,并输出,按照递归的方法,如求abcd的全排序,1:先求abcd后面的bcd全排列(同样先求b后面cd的全排列,然后b与后面的元素依次交换);2:

(转)C#全排列组合算法

全排列组合算法方法: public static List<List<T>> FullCombination<T>(List<T> lstSource){ var n = lstSource.Count; var max = 1 << n;//1乘以2的n次方 var lstResult = new List<List<T>>(); for (var i = 0; i < max; i++) { var lstTem

PHP字符串全排列算法

<?php /** * PHP字符串全排列算法 */ $results = []; $arr = []; function bfs($start) { global $arr; global $results; $queue = []; array_push($queue, $start); while( !empty($queue) ) { $cur = array_shift($queue); if(strlen($cur) === count($arr)) { array_push($re

Leetcode分类解析:组合算法

Leetcode分类解析:组合算法 所谓组合算法就是指:在解决一些算法问题时,需要产生输入数据的各种组合.排列.子集.分区等等,然后逐一确认每种是不是我们要的解.从广义上来说,组合算法可以包罗万象,甚至排序.各种搜索算法都可以算进去.最近读<The Algorithm Design Manual>时了解到这种归类,上网一查,甚至有专门的书籍讲解,而且Knuth的巨著TAOCP的第四卷就叫组合算法,看来还真是孤陋寡闻了!于是最近着重专攻了一下Leetcode中所有相关题目,在此整理一下学习心得.

字符串的排列组合总结

问题1 :输入一个字符串,打印出该字符串中字符的所有排列.例如输入字符串abc,则输出由字符a.b.c所能排列出来的所有字符串abc.acb.bac.bca.cab和cba. 思路:这是个递归求解的问题.递归算法有四个特性:(1)必须有可达到的终止条件,否则程序将陷入死循环:(2)子问题在规模上比原问题小:(3)子问题可通过再次递归调用求解:(4)子问题的解应能组合成整个问题的解. 对于字符串的排列问题.如果能生成n - 1个元素的全排列,就能生成n个元素的全排列.对于只有1个元素的集合,可以直

字符串元素重排高效算法集合

以下各题均有时间复杂度为O(n*n)或以空间换取时间使得时间空间复杂度为O(n)的算法,在此均不考虑. 问题一.字符串移动 字符串为*号和26个字母的任意组合,把*号都移动到最左侧,把字母移到最右侧并保持相对顺序不变,要求时间和空间复杂度最小 .如"afdg**fa**hjfkdsl"变换成"****afdgfahjfkdsl" 此题前后字符串的长度不变,由于最终一边只有'*',另一边为字母,可以设置两个指针fast和slow,当str[fast]不为'*'时,赋值

字符串全排列 java实现

经常会遇到字符串全排列的问题.例如:输入为{'a','b','c'},则其全排列组合为abc,acb,bac,bca,cba,cab.对于输入长度为n的字符串数组,全排列组合为n!种. package Bayes; public class RecursionTree { public static void permutation(char[] s,int from,int to) { if(to<=1) { return; } if(from ==to) { System.out.print