• 题目描述:

输入一个字符串,按字典序打印出该字符串中字符的所有排列。例如输入字符串abc,则打印出由字符a,b,c所能排列出来的所有字符串abc,acb,bac,bca,cab和cba。
输入描述:输入一个字符串,长度不超过9(可能有字符重复),字符只包括大小写字母。

  • 分析:

    虽然题目举例的输入时abc,但并没有说明输入的字符串是按字典序的,所以在打印中的字典序可能会需要一个排序过程。首先,我们可以把字符串看成两部分:第一个字符和它后边的剩余字符组成的字符串。所以,在求所有排列的过程中,我们可以先选择一个字符作为放在第一个位置,即将第一个字符和后边的所有字符依次交换,然后固定第一个位置的字符,再对其后边的所有字符求其所有排列。显然这是一个递归的过程。注意: 递归需要终止的条件,在这里为固定的字符为字符串的最后一个字符。

    //方法一:通过一个set使string序列变成字典序,并且可以消除重复的序列
    
    void permutation(set<string> &res,string &str,int begin,int end)
    { 
    	 if (begin == end)
    		res.insert(str);
    
    	for (int i = begin; i <= end; ++i)
    	{
    		swap(str[begin], str[i]);// 容器string中存在函数swap直接交换string中的两个元素
    		permutation(res, str, begin + 1, end);
    		swap(str[begin], str[i]);
    	}
    }
    
    vector<string> Permutation(string str)
    {
    	vector<string> result;
    	set<string> res;
    
    	permutation(res, str, 0, str.end());
    
    	for (auto &s : res)
    		result.push_back(s);
    	return result;
    }
    
    // 方法二:使用sort先进行排序,但要注意消除重复的序列
    
    void permutation(vector<string> &res, string &str, int begin, int end)
    {
    	if (begin == end)
    		res.push_back(str);
    
    	for (int i = begin; i <= end; ++i)
    	{
    		if (i != begin && str[i] == str[begin]) // 固定某一位的时候遇到相同字符不交换,避免重复
    			continue;
    		swap(str[begin], str[i]);
    		permutation(res, str, begin + 1, end);
    		swap(str[begin], str[i]);
    	}
    }
    
    vector<string> Permutation(string str)
    {
    	vector<string> result;
    
    	permutation(result, str, 0, str.size() - 1);
    	sort(result.begin(), result.end());
    
    	return result;
    }
    
 posted on 2017-05-14 19:06  Bill_LHR  阅读(262)  评论(0编辑  收藏  举报