【题目描述】
输入一个字符串,按字典序打印出该字符串中字符的所有排列。例如输入字符串abc,则按字典序打印出由字符a,b,c所能排列出来的所有字符串abc,acb,bac,bca,cab和cba。
输入描述:
输入一个字符串,长度不超过9(可能有字符重复),字符只包括大小写字母。
示例1
输入 | 输出 |
---|---|
“ab” | [“ab”,“ba”] |
【字典序】
字典序(dictionary order),又称 字母序(alphabetical order),原意是表示英文单词在字典中的先后顺序,在计算机领域中扩展成两个任意字符串的大小关系。
下列单词就是按照字典序进行排列的:
as aster astrolabe astronomy astrophysics at ataman attack baa
【官方代码】
class Solution {
public:
void perm(int pos, string s, set<string> &ret) {
if (pos+1 == s.length()) {
ret.insert(s);
return;
}
// for循环和swap的含义:对于“ABC”,
// 第一次'A' 与 'A'交换,字符串为"ABC", pos为0, 相当于固定'A'
// 第二次'A' 与 'B'交换,字符串为"BAC", pos为0, 相当于固定'B'
// 第三次'A' 与 'C'交换,字符串为"CBA", pos为0, 相当于固定'C'
for (int i = pos; i < s.length(); ++i) {
swap(s[pos], s[i]);
perm(pos+1, s, ret);
swap(s[pos], s[i]);
// 回溯的原因:比如第二次交换后是"BAC",需要回溯到"ABC"
// 然后进行第三次交换,才能得到"CBA"
}
}
vector<string> Permutation(string s) {
if (s.empty()) return {};
set<string> ret;
perm(0, s, ret);
return vector<string>({ret.begin(), ret.end()});
}
};
【B站代码】
class Solution {
public:
vector<string> res;
string path;
vector<string> Permutation(string str) {
if(str == "") return res; //[""] []
//全排列
//可能重复字母 靠在一起 好判断
sort(str.begin(),str.end());
path.resize(str.size());//先开辟好path的空间大小
//全排列函数
dfs(str, 0, 0, 0);
//字典顺序
sort(res.begin(), res.end());
return res;
}
void dfs(string &str, int idx, int start, int state)
{
//已经找到一个排列
if(idx == str.size())
{
res.push_back(path);
return;
}
//单个排列没有排完
//相同字母而言 前后关系
//可能重复排序
//通过控制相对顺序不变确保不重复
if(idx == 0 || str[idx] != str[idx - 1]) start = 0;
//顺序往后
for(int i = start; i < str.size(); i ++)
if(!(state >> i & 1))
{
path[i] = str[idx];
dfs(str, idx + 1, i + 1, state + (1 << i));
}
}
};
//注意左移右移 和 操作符&
/(ㄒoㄒ)/~~感觉这题不简单呀