剑指offer:字符串的排列

题目:

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

思路:

首先确定第一个字母,这种情况下的排列就是剩下字符的所有排列,可以用递归完成,然后依次交换第一个字母和剩下的字母,得到不同起始字母下的所有排列。思路听起来很简单,但是有很多需要注意的点。

首先不需要单独用变量存储每个排列,直接在str上进行交换操作,然后把字符串一次压入result,所以要注意每次交换计算完所有排列后,要再交换回来,不然会有重复。

其次用一个变量start表示当前递归过程第一个字母,所以每次递归要将start+1(即先确定start位置的字母,然后递归后面的字符串),递归的结束条件时start到达最后一个字符,即不需要再交换了。

用循环来实现首字母与剩下字母交换,因为原始字符串也是一个排列,所以交换的位置i从start开始;因为可能有重复的字符,所以当i!=start,并且i和start位置的字符相同时,要跳过这些重复字符,直接i++。

最后得到的所有排列要做一个排序,保证按字典序输出。

参考代码:

在线测试:

https://www.nowcoder.com/practice/fe6b651b66ae47d7acce78ffdd9a96c7?tpId=13&tqId=11180&rp=1&ru=/ta/coding-interviews&qru=/ta/coding-interviews/question-ranking

AC代码:

class Solution {
public:
    vector<string> Permutation(string str) {
        vector<string> result;
	if(str.empty())
		return result;
	Permutation(str, 0, result);
	sort(result.begin(),result.end());
	return result;
    }
	void Permutation(string str, int start, vector<string> &result)
	{
		if(start==str.size()-1)
		{
			result.push_back(str);
			return;
		}
		for(int i=start; i<str.size(); i++)
		{
			if(i!=start && str[i]==str[start])
				continue;
			swap(str[start],str[i]);
			Permutation(str, start+1, result);
			swap(str[start],str[i]);
		}	
	}
};

猜你喜欢

转载自blog.csdn.net/u012991043/article/details/81171407