前言:可能写的思路有些混乱,如果有不懂的或我说错的,还请指教批评 ,本人还是很希望有批评的,因为写了这么多篇博客,没有评论,所以不知道自己的不足,希望能有评论来指正我的不足,来让我改正。
题目:输入一个字符串,按字典序打印出该字符串中字符的所有排列。例如输入字符串abc,则打印出由字符a,b,c所能排列出来的所有字符串abc,acb,bac,bca,cab和cba。
注意,这里还需要按字典序排序,我第一次做就忘记了这一点,接下来我们说一下这道题的思路。
思路:全排列这种我们初中应该就学过。例如给出个字符串abc,有如下排列顺序。
由上图可知字符串abc全排列共有六种可能,我们把问题分的更小一些就是,字符串第一个位置可能存放a或b或c,
第二个位置也可能存放a或b或c,第三个位置同理也可能存放a或b或c。当第一个位置存放a的时候后边剩下字符串的排序种类就是当a在第一个位置的时候的排序种类,同理b放在第一位的时候,排序种类=后边剩下的字符的排序种类。以此类推,当第一个数是ab的时候,排序种类=剩下字符串的排序种类。
所以,我们可以把问题看成一个递归,先把第一个数确定,算剩下字符串的排序种类,而算剩下字符串的排序种类的方法又可先确定第二个数。如下图
这个图是从牛客王看见的,我觉得很号的帮助了我理解。
我们看这种图,多次使用循环+交换,并且下一次循环的字符串是上一次循环+交换的结果,这样我们几句很容易写出一个递归函数。
代码:
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
public class Solution26 {
public ArrayList<String> Permutation(String str) {
ArrayList<String> arr = new ArrayList<String>();
Set set = new HashSet<String>();
arr = new ArrayList(find(set, new StringBuffer(str), 0, str.length()));
Collections.sort(arr);//按字典序排序
return arr;
}
public HashSet<String> find(Set set, StringBuffer str, int begin, int end) {
String s = new String(str);//避免交换一次之后改变了str的值,所以用String先存一下。
for (int i = begin; i < end; i++) {
char temp = str.charAt(i);//开始交换
str.setCharAt(i, str.charAt(begin));
str.setCharAt(begin, temp);
if (end - begin == 1) {//如果递归到字符串最后两个的时候,将结果返回。
set.add(new String(str));// 用set存去重
}
find(set, str, begin + 1, end);
str = new StringBuffer(s);//将str恢复成交换前的
}
return (HashSet<String>) set;
}