Question
输入一个字符串,按字典序打印出该字符串中字符的所有排列。例如输入字符串abc,则打印出由字符a,b,c所能排列出来的所有字符串abc,acb,bac,bca,cab和cba。
输入描述:输入一个字符串,长度不超过9(可能有字符重复),字符只包括大小写字母。
关键词:全排列 回溯法
Solution
回溯法
回溯法:对于下一步所有可行的走法,判定是否存在可能的目标路径,如果存在就继续下一步,如果没有或尝试完所有走法,就返回上一步(类似DFS)。
实际写法:建立数组储存是否用过该字符(初始化全false)-标志位,先取第i个字符,该字符标志位需为false(代表该字符并没有在path中),path.append(字符[i]),并标志位[i]设true,递归i+1(表示path已经有了i+1个字符,终止条件为 i==str.len(),ans.append(path),返回),最后重置状态(递归结束代表已经尝试了所有走法,需要返回上一节点的状态,即:标志位[i]=false,path.remove(-1))。
时间复杂度:O(N!)
空间复杂度:O(N!)
- Python
class Solution:
def __init__(self):
self.ans = []
self.path = ''
self.state = []
def Permutation(self, ss):
if not ss:
return ss;
self.state = [False] * len(ss)
def huisu(cur_len):
if cur_len == len(ss):
if self.path not in self.ans:
self.ans.append(self.path)
return
for i in range(len(ss)):
# 只走可行的走法,即path还没用过的字符
if not self.state[i]:
# 更新状态
self.state[i] = True
self.path += ss[i]
# 尝试所有走法
huisu(cur_len + 1)
# 重置状态
self.state[i] = False
self.path = self.path[:-1]
huisu(0)
return self.ans
- C++
class Solution {
public:
vector<string> ans;
string path;
vector<bool> state;
vector<string> Permutation(string str) {
if(str.size() ==0)
return ans;
for(int i=0; i<str.size(); i++)
state.push_back(false);
huisu(str, 0);
return ans;
}
void huisu(string str, int len){
if(len == str.size()){
if(find(ans.begin(), ans.end(), path) == ans.end())
ans.push_back(path);
return;
}
for(int i=0; i<str.size(); i++){
if(!state[i]){
state[i] = true;
path.push_back(str[i]);
huisu(str, len + 1);
state[i] = false;
path.pop_back();
}
}
}
};