字符串的排列组合总结

问题1
:输入一个字符串,打印出该字符串中字符的所有排列。例如输入字符串abc,则输出由字符a、b、c所能排列出来的所有字符串abc、acb、bac、bca、cab和cba。

思路:这是个递归求解的问题。递归算法有四个特性:(1)必须有可达到的终止条件,否则程序将陷入死循环;(2)子问题在规模上比原问题小;(3)子问题可通过再次递归调用求解;(4)子问题的解应能组合成整个问题的解。

对于字符串的排列问题。如果能生成n -
1个元素的全排列,就能生成n个元素的全排列。对于只有1个元素的集合,可以直接生成全排列。全排列的递归终止条件很明确,只有1个元素时。


#include <iostream>

using namespace std;

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

void Permutation(char *pStr)//提供的公共接口
{
if (pStr == NULL)
{
return;
}
Permutation(pStr, pStr);
}

void Permutation(char *pStr, char *pBegin)
{
if(*pBegin == ‘\0‘)
{
cout << pStr << endl;
}
else
{
for (char *pCh = pBegin; *pCh != ‘\0‘; ++pCh)
{
swap(*pCh,*pBegin);//交换
Permutation(pStr, pBegin + 1);
swap(*pCh,*pBegin);//恢复还原
}
}
}
void swap(char a, char b)
{
char temp = a;
a = b;
b = temp;
}
int main()
{
char string[100];
while(cin>>string)
Permutation(string);
return 0;
}

问题是存在重复时无法实现

去重的全排列就是从第一个数字起每个数分别与它后面非重复出现的数字交换


#include <iostream>

using namespace std;

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

void Permutation(char *pStr)//提供的公共接口
{
if (pStr == NULL)
{
return;
}
Permutation(pStr, pStr);
}
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)
{
if(*pBegin == ‘\0‘)
{
cout << pStr << endl;
}
else
{
for (char *pCh = pBegin; *pCh != ‘\0‘; ++pCh)
{
if(IsSwap(pBegin , pCh))
{
swap(*pCh,*pBegin);//交换
Permutation(pStr, pBegin + 1);
swap(*pCh,*pBegin);//恢复还原
}
}
}
}
void swap(char a, char b)
{
char temp = a;
a = b;
b = temp;
}
int main()
{
char string[100];
while(cin>>string)
Permutation(string);
return 0;
}

问题2:输入一个字符串,输出该字符串中字符的所有组合。举个例子,如果输入abc,它的组合有a、b、c、ab、ac、bc、abc。

思路:同样是用递归求解。可以考虑求长度为n的字符串中m个字符的组合,设为C(n,m)。原问题的解即为C(n, 1), C(n,
2),...C(n, n)的总和。对于求C(n, m),从第一个字符开始扫描,每个字符有两种情况,要么被选中,要么不被选中,如果被选中,递归求解C(n-1,
m-1)。如果未被选中,递归求解C(n-1, m)。不管哪种方式,n的值都会减少,递归的终止条件n=0或m=0。假设我们想在长度为n的字符串中求m个字符的组合。我们先从头扫描字符串的第一个字符。针对第一个字符,我们有两种选择:一是把这个字符放到组合中去,接下来我们需要在剩下的n-1个字符中选取m-1个字符;而是不把这个字符放到组合中去,接下来我们需要在剩下的n-1个字符中选择m个字符。这两种选择都很容易用递归实现。


#include <iostream>
using namespace std;
#include <vector>
#include <string.h>
//函数功能 : 从一个字符串中选m个元素
//函数参数 : pStr为字符串, m为选的元素个数, result为选中的
//返回值 : 无
void Combination_m(char *pStr, int m, vector<char> &result)
{
if(pStr == NULL || (*pStr == ‘\0‘&& m != 0))
return;
if(m == 0) //递归终止条件
{
for(unsigned i = 0; i < result.size(); i++)
cout<<result[i];
cout<<endl;
return;
}
//选择这个元素
result.push_back(*pStr);
Combination_m(pStr + 1, m - 1, result);
result.pop_back();
//不选择这个元素
Combination_m(pStr + 1, m, result);
}
//函数功能 : 求一个字符串的组合
//函数参数 : pStr为字符串
//返回值 : 无
void Combination(char *pStr)
{
if(pStr == NULL || *pStr == ‘\0‘)
return;
int number = strlen(pStr);
for(int i = 1; i <= number; i++)
{
vector<char> result;
Combination_m(pStr, i, result);
}
}
int main()
{
char string[100];
while(cin>>string)
Combination(string);
return 0;
}

由于组合可以是1个字符的组合,2个字符的字符……一直到n个字符的组合,因此在函数void
Combination(char* pStr),我们需要一个for循环。另外,我们一个vector来存放选择放进组合里的字符。

3.打靶问题,靶一共有10环,求10次打靶命中90环的可能。

分析,每次有11种可能,1-10环,或未中


#include <iostream>
using namespace std;
#include <vector>
#include <string.h>
//函数功能 : 求解number次打中sum环的种数
//函数功能 : 求解number次打中sum环的种数
//函数参数 : number为打靶次数,sum为需要命中的环数,result用来保存中间结果,total记录种数
//返回值 : 无
void ShootProblem_Solution1(int number, int sum, vector<int> &result, int *total)
{
if(sum < 0 || number * 10 < sum) //加number * 10 < sum非常重要,它可以减少大量的递归,类似剪枝操作
return;
if(number == 1) //最后一枪
{
if(sum <= 10) //如果剩余环数小于10,只要最后一枪打sum环就可以了
{
for(unsigned i = 0; i < result.size(); i++)
cout<<result[i]<<‘ ‘;
cout<<sum<<endl;
(*total)++;
return;
}
else
return;
}
for(unsigned i = 0; i <= 10; i++) //命中0-10环
{
result.push_back(i);
ShootProblem_Solution1(number-1, sum-i, result, total); //针对剩余环数递归求解
result.pop_back();
}
}
//提供的公共接口
void ShootProblem(int number, int sum)
{
int total = 0;
vector<int> result;
ShootProblem_Solution1(number, sum, result, &total);
cout<<"total nums = "<<total<<endl;
}
int main()
{
int number,sum;
cin>>number>>sum;
// while(cin>>number>>sum)
ShootProblem(number,sum);
return 0;
}

字符串的排列组合总结,布布扣,bubuko.com

时间: 2025-01-08 06:09:24

字符串的排列组合总结的相关文章

字符串的排列组合

1.字符串的组合 字符串的组合,有字符串abc,它的所有组合为a,b,c,ab,ac,abc.求字符串的组合可以使用递归的方法,程序如下: void print(string &s,int start,vector<char> &t) { if(start==s.size()) { return ; } int i=0; for(i=start;i<s.size();++i) { t.push_back(s[i]); //使用递归+回溯的方法求组合 vector<c

c++字符串的排列组合

#include <iostream> #include <string.h> using namespace std; static int sum = 0; void Swap(char &a, char &b) { char tmp = a; a = b; b = tmp; } void Grial(char *s1, char *s2) { if (s1 == NULL || s2 == NULL)return; if (*s2 == '\0') cout

字符串排列组合问题

一.全排列无重复字符 #include<stdio.h> #include<string.h> char buf[1024]; void func(int index); void swap(int index1,int index2); int main() { memset(buf,0,sizeof(buf)); sprintf(buf,"abc"); func(0); return 0; } void func(int index) { if(index

9.9递归和动态规划(五)——确定某字符串的所有排列组合

/** * 功能:确定某字符串的所有排列组合. */ 注意:不考虑重复字符.若考虑重复字符,只需在加入permulations时去掉重复的字符串即可. /** * 思路:元素由少到多,将新的元素塞进所有字符串中间的任意可能位置. * @param str * @return */ public static ArrayList<String> getPerms(String str){ if(str==null) return null; ArrayList<String> per

编写一个方法,确定某字符串的所有排列组合

public static ArrayList<String> getPerms(String str) { if(str==null) return null; ArrayList<String> permutations=new ArrayList<String>(); if(str.length()==0)//终止条件 { permutations.add(""); return permutations; } char first=str.c

排列组合问题(递归实现)

在做递归问题时,要保证对递归跳跃的信任,继而对相应的问题寻找其递归实现 (1)组合:先从原始数组中选择一个,再从剩下的集合中选择m-1个:而后,再从剩下的集合中挑选m个元素. /*组合代码(eg:5选2)*/ int a[5]={1,2,3,4,5};//原始数组 int b[2];//挑选的结果 const int need=2;//需要选择的个数 void combine(int start,int end,int x) { if(x==need) { //(1)打印组合的内容 /* for

【编程题目】字符串的排列(字符串)★

53.字符串的排列(字符串).题目:输入一个字符串,打印出该字符串中字符的所有排列.例如输入字符串 abc,则输出由字符 a.b.c 所能排列出来的所有字符串abc.acb.bac.bca.cab 和 cba. 这道题花了我一天,要好好总结! 思路:这道题目感觉有些难,主要是字符串中的字符可能会有重复.我的想法是把一共有多少种字符和每种字符出现的次数统计出来,每个位置对这些字符变量,下一个位置的可用字符减小,再遍历. /* 53.字符串的排列(字符串). 题目:输入一个字符串,打印出该字符串中字

排列组合的实现

数据库环境:SQL SERVER2008R2 先说一下需求:实现1,2,3的排列组合,即123,132,213,231,312,321. 哈哈,你没看错,需求这是这么短短的一句话. 我想到了2个方法,都可以实现需求.下面我分别介绍这2种实现方法. 方法一:建一个表xx,往xx表中插入1,2,3自然数列,简单起见,把自然数改成字符串, 然后xx表和xx表进行FULL JOIN(全外连接)得到结果集tmp,结果集tmp再和xx表进行LEFT JOIN(左连接), 关联的条件是当前xx表的数据不存在结

【Java中 任意几个数字获取其所有的排列组合】

今天在工作中碰到一个问题,在java中输入比如1,2,3  三个数 我想要得到其所有的排列组合 比如 123,312,132,231,213,321 这些 上网找了找别人的算法,稍加整理,分享给大家代码如下 import java.util.Arrays;                        //用于数组输出. import java.util.LinkedList; import java.util.List; public class test { static String to