1. 题目描述
输入一个字符串,打印出该字符串中字符的所有排列。
你可以以任意顺序返回这个字符串数组,但里面不能有重复元素。
2. 思路
回溯算法的模板:
private void backtrack("原始参数") {
//终止条件(递归必须要有终止条件)
if ("终止条件") {
//一些逻辑操作(可有可无,视情况而定)
return;
}
for (int i = "for循环开始的参数"; i < "for循环结束的参数"; i++) {
//一些逻辑操作(可有可无,视情况而定)
//做出选择
//递归
backtrack("新的参数");
//一些逻辑操作(可有可无,视情况而定)
//撤销选择
}
}
根据模板有一个大概的思路,再修改下条件即可。
题目思路
(1) 递归字符串,将字符串的每个字符加进结果并标记该字符的下标,每次遍历都会从头开始遍历;
(2)直到结果字符串的长度与题目的字符串长度相等。
(3) 递归往回走时,需要撤销标记(回溯)。
(4)注意标记的是字符串的下标,所以对于对于重复元素需要用Set容器处理。
3. 代码
class Solution {
public String[] permutation(String s) {
char[] str = s.toCharArray();
Set<String> res = new HashSet<String>();
backtrack(str,res,"",new boolean[str.length]);
return res.toArray(new String[str.length]);
}
public void backtrack(char[] str, Set<String> res, String temp, boolean[] visited){
//递归终止条件:结果字符串的长度跟题目给出的字符串相等
//将字符串加进结果,结束递归
//因为可能有重复字符串,所以需要用set添加结果
if(temp.length() == str.length){
res.add(temp);
return;
}
//每次遍历都从头开始
for(int i = 0 ;i < str.length; i++){
if(visited[i] == true)//跳过已加入的字符
continue;
//加入结果并标记字符
visited[i] = true;//这里标记的下标,所以当有重复元素时,还需要用set处理
backtrack(str, res, temp+str[i], visited);
visited[i] = false;//回溯
}
}
}