输入一个字符串,打印出该字符串中字符的所有排列。
你可以以任意顺序返回这个字符串数组,但里面不能有重复元素。
示例:
输入:s = "abc"
输出:["abc","acb","bac","bca","cab","cba"]
参考:力扣
vis存储当前字符是否加入了数组
先排序-主要是为了处理相同字符
回溯法:
- 如果长度满足要求,加入即可
- 遍历每个字符
- 如果vis true则说明已经加入了 跳过
- 如果和前一个重复并且前一个未加入(确保加入次序为从左到右,即一次)跳过
- 加入字符 进入下一回溯 删除字符
把结果处理输出
注意:重点在于重复字符处理部分
class Solution {
// 结果
List<String> rec;
boolean[] vis;
public String[] permutation(String s) {
// s的长度
int n = s.length();
// 储存结果
rec = new ArrayList<String>();
// 如果该位置已被填过即为true
vis = new boolean[n];
char[] arr = s.toCharArray();
// 先排序,主要是防止相同字符
Arrays.sort(arr);
// 临时变量存储
StringBuffer perm = new StringBuffer();
// 回溯法
backtrack(arr, 0, n, perm);
int size = rec.size();
String[] recArr = new String[size];
for (int i = 0; i < size; i++) {
recArr[i] = rec.get(i);
}
return recArr;
}
// i-遍历到第几个字符
public void backtrack(char[] arr, int i, int n, StringBuffer perm) {
if (i == n) {
// 长度符合要求,加入一个到结果
rec.add(perm.toString());
return;
}
for (int j = 0; j < n; j++) {
// 如果已经加入 或者 当前不是重复字符串第一个未填入的 (和前一个重复,但是前一个未填入)
if (vis[j] || (j > 0 && !vis[j - 1] && arr[j - 1] == arr[j])) {
continue;
}
// 加入字符
vis[j] = true;
perm.append(arr[j]);
backtrack(arr, i + 1, n, perm);
// 回溯
perm.deleteCharAt(perm.length() - 1);
vis[j] = false;
}
}
}