作者:翟天保Steven
版权声明:著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处
输入一个长度为 n 字符串,打印出该字符串中字符的所有排列,你可以以任意顺序返回这个字符串数组。
例如输入字符串ABC,则输出由字符A,B,C所能排列出来的所有字符串ABC,ACB,BAC,BCA,CBA和CAB。
数据范围:n<10
要求:空间复杂度 O(n!),时间复杂度 O(n!)
输入:
"aab"
返回值:
["aab","aba","baa"]
本题考察算法-搜索算法的使用。具体实现列了三种写法:
解法一:next_permutation函数
解法二:仿写next_permutation函数
解法三:深度优先遍历DFS
解法一:next_permutation函数
- class Solution {
- public:
- vector<string> Permutation(string str)
- {
- vector<string> ans;
- // 判空
- if (str.empty())
- return ans;
- // 排序
- sort(str.begin(), str.end());
- // 全排列,next_permutation会将str转为下一个排列
- do {
- ans.push_back(str);
- } while (next_permutation(str.begin(), str.end()));
- return ans;
- }
- };
解法二:仿写next_permutation函数
- class Solution {
- public:
- vector<string> Permutation(string str)
- {
- vector<string> ans;
- // 判空
- if(str.size() == 0)
- return ans;
- // 排序
- sort(str.begin(),str.end());
- // 全排列
- do {
- ans.push_back(str);
- } while (nextPermutation(str));
- return ans;
- }
-
- // 变换为下个排列
- bool nextPermutation(string &str)
- {
- // len为字符串长度
- int len = str.size();
- // 通过for循环,使得i最终位置是从右向左的首个正序的起始点
- int i = len-2;
- for(;i>=0 && str[i]>=str[i+1];i--);
- // 若i小于0,说明此时字符串已是反序,全排列已完毕
- if(i < 0 )
- return false;
- // 通过for循环,找到比i大的字符中最小的那个,i和j交换
- // 交换后,i后面的字符串应该是反序状态
- int j = len-1;
- for(;j>=0 && str[j]<=str[i];j--);
- char temp = str[i];
- str[i] = str[j];
- str[j] = temp;
- // 将i后面的字符串反转成正序,继续找新的排列
- for(int a = i+1,b = len-1;a < b;a++,b--)
- {
- temp = str[a];
- str[a] = str[b];
- str[b] = temp;
- }
- return true;
- }
- };
解法三:深度优先遍历DFS
- class Solution {
- public:
- // 深度优先遍历
- void DFS(vector<string> &res, string &str, string &temp, vector<int> &vis)
- {
- // 临时字符串满了加入输出
- if(temp.length() == str.length())
- {
- res.push_back(temp);
- return;
- }
- // 遍历所有字符选取一个加入
- for(int i = 0; i < str.length(); i++)
- {
- // 如果该字符已经被加入了则不需要再加入了
- if(vis[i])
- continue;
- // 当前的字符str[i]与同一层的前一个字符str[i-1]相同且str[i-1]还没用过,则跳过,避免重复
- if(i > 0 && str[i - 1] == str[i] && !vis[i - 1])
- continue;
- // 标记为使用过
- vis[i] = 1;
- // 加入临时字符串
- temp.push_back(str[i]);
- // 深度优先遍历
- DFS(res, str, temp, vis);
- // 回溯
- vis[i] = 0;
- temp.pop_back();
- }
- }
-
- vector<string> Permutation(string str)
- {
- // 先按字典序排序,使重复字符串相邻
- sort(str.begin(), str.end());
- // 标记每个位置的字符是否被使用过s
- vector<int> vis(str.size(), 0);
- vector<string> res;
- string temp;
- // 深度优先遍历
- DFS(res, str, temp, vis);
- return res;
- }
- };