题目
题号:27
题目名:字符串的排列
编程语言
Java
题目描述
输入一个字符串,按字典序打印出该字符串中字符的所有排列。例如输入字符串abc,则按字典序打印出由字符a,b,c所能排列出来的所有字
符串abc,acb,bac,bca,cab和cba。
输入描述:
输入一个字符串,长度不超过9(可能有字符重复),字符只包括大小写字母。
初次思路
https://leetcode-cn.com/problems/permutations-ii/与力扣47题全排列 II类似
要点是有重复,但是要输出所有不重复的组合全排列
是非常经典的dfs问题,但是要遍历的过程中将重复的去掉
我这里考虑使用一个数组去记录使用过的字母,如果使用过就为true否则为false
因为已经排序过,所以一样的字母会排在一起,然后因为是从前往后遍历,所以需要记录第一次重复的字符,如果字符重复,就不进行遍历
这里不能使用前后比较去重!!!
解题代码
public class Solution {
public ArrayList<String> Permutation(String str) {
ArrayList<String> strs = new ArrayList<>();
//非空校验
if (str == null || str.length() == 0) return strs;
char[] chars = str.toCharArray();//将字符串咋换成数组
Arrays.sort(chars);//排序
boolean[] isUsed = new boolean[str.length()];//看看哪些用过
StringBuilder sb = new StringBuilder();//存放使用过的字符
//dfs遍历
dfs(strs, sb, chars, isUsed);
return strs;
}
private void dfs(ArrayList<String> strs, StringBuilder sb, char[] chars, boolean[] isUsed) {
//如果添加完毕
if (sb.length() == chars.length) {
strs.add(sb.toString());
return;
}
//定义一个之指针记录上次使用的字母
char lastChar = ' ';
for (int i = 0; i < chars.length; i++) {
//如果该字母没有被使用过,加入当前位置
if (lastChar!=chars[i]&&!isUsed[i]) {
sb.append(chars[i]);//如果该字母没有被使用过,加入当前位置
isUsed[i] = true;
dfs(strs, sb, chars, isUsed);
lastChar = chars[i];
sb.deleteCharAt(sb.length() - 1);//剪枝
isUsed[i] = false;
}
}
}
}
算法练习代码我都开源在码云上,有需要的朋友可以看看