Trace
6.22 每日一题
传送门:https://leetcode-cn.com/problems/zi-fu-chuan-de-pai-lie-lcof/
Problem
输入一个字符串,打印出该字符串中字符的所有排列。
你可以以任意顺序返回这个字符串数组,但里面不能有重复元素。
示例
1 2
| 输入:s = "abc" 输出:["abc","acb","bac","bca","cab","cba"]
|
数据范围
dfs
先求出所有排列结果,然后用$set$去重。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| class Solution { public: int d[9]; map<int,bool> vis; set<string> ans; void dfs(int k,string s){ if(k==s.size()){ string t=""; for(int i=0;i<s.size();i++){ t=t+s[d[i]]; } ans.insert(t); return ; } for(int i=0;i<s.size();i++){ if(vis[i]==false){ vis[i]=true; d[k]=i; dfs(k+1,s); vis[i]=false; } }
} vector<string> permutation(string s) { dfs(0,s); vector<string> per; per.assign(ans.begin(),ans.end()); return per; } };
|
时间复杂度$O(2^8*s)$
运行时间534ms。
dfs
先求出所有排列结果,然后用$vector$排序再去重。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| class Solution { public: int d[9]; map<int,bool> vis; vector<string> ans; void dfs(int k,string s){ if(k==s.size()){ string t=""; for(int i=0;i<s.size();i++){ t=t+s[d[i]]; } ans.push_back(t); return ; } for(int i=0;i<s.size();i++){ if(vis[i]==false){ vis[i]=true; d[k]=i; dfs(k+1,s); vis[i]=false; } }
} vector<string> permutation(string s) { dfs(0,s); sort(ans.begin(),ans.end()); ans.erase(unique(ans.begin(),ans.end()),ans.end()); return ans; } };
|
运行时间424ms。
dfs+剪枝
在$dfs$的时候对重复的排列进行剪枝。
具体做法:先对$s$进行排序,使得相同元素相邻,然后在$dfs$的过程中,对$s[i]==s[i-1],vis[i-1]==true)$剪枝,因为相同元素$dfs$出来的结果一定相同,后面条件避免在一次排列中相同字符只能用一次。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| class Solution { public: int d[9]; map<int,bool> vis; vector<string> ans; void dfs(int k,string s){ if(k==s.size()){ string t=""; for(int i=0;i<s.size();i++){ t=t+s[d[i]]; } ans.push_back(t); return ; } for(int i=0;i<s.size();i++){ if(i>0&&s[i]==s[i-1]&&vis[i-1]==true) continue; if(vis[i]==false){ vis[i]=true; d[k]=i; dfs(k+1,s); vis[i]=false; } }
} vector<string> permutation(string s) { sort(s.begin(),s.end()); dfs(0,s); return ans; } };
|
运行时间116ms。