1.题目描述
输入一个字符串,打印出该字符串中字符的所有排列。
你可以以任意顺序返回这个字符串数组,但里面不能有重复元素。
示例:
输入:s = "abc"
输出:["abc","acb","bac","bca","cab","cba"]
2.解题思路与代码
2.1 解题思路
题目要求列出字符串的全排列,我们可以考虑使用递归来遍历字符串。使用 index 来记录选择字符的次数,由于不能重复,选择使用一个辅助数组 tmp[] 来记录当前路径下的遍历情况,对遍历过的字符进行记录,下一轮来时首先判断是否遍历过,遍历过的话则跳过该字符。当选择次数等于字符串长度时,表明一组排列完成,记入结果中。每一次递归函数调用完成之后需要恢复现场,将当前字符剔除,并将 tmp 对应位置置为 false。在每一次递归调用方法的时候,需要从字符串的第 0 位开始选择字符,这样才能选出所有的排列情况。相关细节在代码中进行注释。
2.2 代码
class Solution {
Set<String> ans = new HashSet<>();
public String[] permutation(String s) {
// 使用辅助数组记录字符筛选情况
boolean[] tmp = new boolean[s.length()];
process(s.toCharArray(), 0, tmp, new StringBuilder());
return ans.toArray(new String[0]);
}
public void process(char[] chars, int index, boolean[] tmp, StringBuilder builder) {
if (index == chars.length) {
ans.add(builder.toString());
return;
}
for (int i = 0; i < chars.length; i++) {
// 当字符选择过时,直接跳过
if (tmp[i]) {
continue;
}
// 字符没有选择过,将字符放入 builder中,并且 tmp 改为 true
builder.append(chars[i]);
tmp[i] = true;
// 递归调用处理
process(chars, index + 1, tmp, builder);
// 递归调用完成后恢复现场,tmp 改为 false,并且将字符从 builder 中删除
tmp[i] = false;
builder.delete(builder.length() - 1, builder.length());
}
}
}
2.3 测试结果
通过测试
3.总结
- 每一次递归调用都需要从字符串角标 0 开始选择字符
- 使用 tmp 数组记录字符选择情况,如果选择过直接跳过
- 每一次字符选择处理完成之后需要剔除选择的字符以及重置 tmp 中字符选择状态