相关题目:
牛客网 剑指Offer题:字符串的排列
题目描述:
输入一个字符串,按字典序打印出该字符串中字符的所有排列。例如输入字符串abc,则打印出由字符a,b,c所能排列出来的所有字符串abc,acb,bac,bca,cab和cba。
输入描述:
输入一个字符串,长度不超过9(可能有字符重复),字符只包括大小写字母。
全排列算法解决思路:
递归解决方式:
这里以abc的全排列为例子,由图可以看出可以用DFS的思路解决,对可可选择的字母进行遍历,不断递归直到可选字母集合为空,此时就是一个排列顺序。
参考代码:
private void Permutation(ArrayList<String> resList, StringBuilder sb, String str) {
if (str.length() == 0) {
resList.add(sb.toString());
}
else {
for (int i = 0; i < str.length(); i++) {
String curValue = String.valueOf(str.charAt(i));
sb.append(curValue);
//这里是处理后面参数str拼接问题,要将已排序的数据移除
if (i == 0) {
Permutation(resList, sb, str.substring(i+1));
} else if (i == str.length() - 1) {
Permutation(resList, sb, str.substring(0, i));
} else
Permutation(resList, sb, str.substring(0, i) + str.substring(i+1));
//清除状态
sb.deleteCharAt(sb.length()-1);
}
测试结果:
对于全排列还有另外一种,就是所要全排列的数据中有重复项,这样我们就需要在全排列前做一个判断,对于重复项,我们只对它们中的一个进行交换,即交换前先判断一下该数据后面是否有重复,如果有重复就跳过,只对最后面的那个进行全排,这样就可以避免重复了。
参考代码:
private void Permutation(ArrayList<String> resList, StringBuilder sb, String str) {
if (str.length() == 0) {
resList.add(sb.toString());
}
else {
for (int i = 0; i < str.length(); i++) {
//增加一个判断
if (isChange(str, i)) {
String curValue = String.valueOf(str.charAt(i));
sb.append(curValue);
//这里是处理后面参数str拼接问题,要将已排序的数据移除
if (i == 0) {
Permutation(resList, sb, str.substring(i+1));
} else if (i == str.length() - 1) {
Permutation(resList, sb, str.substring(0, i));
} else
Permutation(resList, sb, str.substring(0, i) + str.substring(i+1));
//清除状态
sb.deleteCharAt(sb.length()-1);
}
}
}
}
//判断要不要交换
private boolean isChange(String str, int i) {
//遍历后面看看有没有重复的,重复的话就不换了,多个重复只换一个就好
for (int j = i + 1; j < str.length(); j++) {
if (str.charAt(j) == str.charAt(i)) {
return false;
}
}
return true;
}
测试结果:
加了这个判断之后就可以对含有重复项的数据进行全排列啦
非递归解决方式:
TODO…