【剑指offer】字符串的排列

来源:互联网 发布:vr全景合成软件 编辑:程序博客网 时间:2024/06/11 03:31

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

无重复字符串排列分析:全排列首先想到的是递归方法。给一个没有重复的字符串,把它拆分成两部分:第一个字符和剩下的字符。把第一个字符和剩下的每一个字符依次交换位置,每次交换位置后相当于确定了第一个位置,还需要继续确定剩余的位置,因此我们把剩余的字符看成一个整体再次全排列(即递归),这样剩余的字符为空时输出字符串(即递归出口)。

程序:

void fullorder(string str,vector<string>& res,int start){if(start==str.size())res.push_back(str);  //当一个排序完成时,把它加入到容器;else {int end=start;while(end<str.size()){swap(str[start],str[end]);fullorder(str,res,start+1);end++;}}}vector<string> Permutation(string str) {    vector<string> res;if(str.empty()) return res;int k=0;fullorder(str,res,k);return res;}

有重复字符串排列分析:当给的字符串有重复字符时,要求全排列依旧是上面的递归方法。我们只需要在剩余字符串的全排列过程中判断从剩余字符串开始到将发生交换字符的前一个字符区间内是否有字符和即将交换的字符相同,若存在则跳过此字符和后面的字符依次交换,避免出现重复的排序。因为此区间中和即将交换的字符相同的字符已经和区间中的每一个字符交换过,再次交换就重复了。

程序:

#include <iostream>#include <string>#include <vector>#include <algorithm>using namespace std;void fullorder(string str,vector<string>& res,int start){if(start==str.size())res.push_back(str);  //当一个排序完成时,把它加入到容器;else {int end=start;while(end<str.size()){/*如果在[start,end)区间中有和str[end]相同的字符str[i],那么str[i]必定会和区间中的其他字符交换,再让str[end]和区间的其他字符交换就会重复*/bool isrepeat=false;for(int i=start;i<end;i++){if(str[end]==str[i]) {isrepeat=true;break;}}if(!isrepeat){swap(str[start],str[end]);fullorder(str,res,start+1);}end++;}}}vector<string> Permutation(string str) {    vector<string> res;if(str.empty()) return res;int k=0;fullorder(str,res,k);return res;}int main(){string s="aabc";vector<string> t=Permutation(s);  int i=0;while(i<t.size())cout<<t[i++]<<endl;return 0;}


原创粉丝点击