https://leetcode-cn.com/problems/zi-fu-chuan-de-pai-lie-lcof/
思路:
d
f
s
dfs
dfs+回溯,注意判重即可。
自己实现的究极暴力版本:
class Solution {
public:
bool vis[8]={0};
int pos[8]={0};
vector<string> ans;
void dfs(int idx,string &s)
{
int siz=s.size();
if(idx==siz)
{
string res(idx,' ');
for(int i=0;i<idx;i++)
res[i]=s[pos[i]];
ans.push_back(res);
return;
}
for(int i=0;i<siz;i++)
{
if(vis[i])
continue;
vis[i]=1;
pos[idx]=i;
dfs(idx+1,s);
vis[i]=0;
}
}
vector<string> permutation(string s) {
sort(s.begin(),s.end());
if(!s.size())
return ans;
dfs(0,s);
sort(ans.begin(),ans.end());
ans.erase(unique(ans.begin(),ans.end()),ans.end());
return ans;
}
};
然而这种去重方式太暴力了,我们优化一下,显然在一次深搜过程中,任意一个字符在位置 i i i只能出现 1 1 1次,否则一定会产生重复的情况。这种方式的深搜返回的结果一定是有序的。
class Solution {
public:
bool vis[8]={0};
int pos[8]={0};
vector<string> ans;
void dfs(int idx,string &s)
{
int siz=s.size();
if(idx==siz)
{
string res(idx,' ');
for(int i=0;i<idx;i++)
res[i]=s[pos[i]];
ans.push_back(res);
return;
}
bool check[26]={0};
for(int i=0;i<siz;i++)
{
if(vis[i]||check[s[i]-'a'])
continue;
check[s[i]-'a']=1;
vis[i]=1;
pos[idx]=i;
dfs(idx+1,s);
vis[i]=0;
}
}
vector<string> permutation(string s) {
sort(s.begin(),s.end());
if(!s.size())
return ans;
dfs(0,s);
return ans;
}
};
因为返回的顺序是任意的,所以我们可以选择交换元素的方式来实现,这种方式结果并不一定有序。
class Solution {
public:
vector<string> ans;
void dfs(int idx,string &s)
{
int siz=s.size();
if(idx==siz)
{
ans.push_back(s);
return;
}
bool vis[26]={0};
for(int i=idx;i<siz;i++)
{
if(vis[s[i]-'a'])
continue;
vis[s[i]-'a']=1;
swap(s[idx],s[i]);
dfs(idx+1,s);
swap(s[idx],s[i]);
}
}
vector<string> permutation(string s) {
sort(s.begin(),s.end());
if(!s.size())
return ans;
dfs(0,s);
return ans;
}
};
利用库函数,快的飞起,而且用这种方式计算出的结果是有序的。
class Solution {
public:
vector<string> permutation(string s) {
sort(s.begin(),s.end());
vector<string> ans;
do
{
ans.push_back(s);
}while(next_permutation(s.begin(),s.end()));
return ans;
}
};