题目描述
输入一个字符串,按字典序打印出该字符串中字符的所有排列。例如输入字符串abc,则打印出由字符a,b,c所能排列出来的所有字符串abc,acb,bac,bca,cab和cba。
输入描述: 输入一个字符串,长度不超过9(可能有字符重复),字符只包括大小写字母。
这里尤其需要注意2点:1.所有组合不能重复,比如输入"aa", 那么输出的结果应当是“aa” ; 2. 输出结果按字典序排序
如果用《剑指offer》上的方法,显然这两点都不能满足,比如输入"abc",输出结果为:"abc" "acb" "bac" "bca" "cba" "cab" ,如果输入"aa",输出解过为"aa" "aa" 。显然,这两种结果都是有问题的。
下面是《剑指offer》版本的代码:
1 import java.util.ArrayList; 2 import java.util.List; 3 public class Solution { 4 private List<String> list = new ArrayList<>(); 5 private StringBuffer buffer; 6 public ArrayList<String> Permutation(String str) { 7 if(str==null||str.length()==0) return (ArrayList<String>) list; 8 buffer = new StringBuffer(str); 9 PermutationCore(0); 10 return (ArrayList<String>) list; 11 } 12 public void PermutationCore(int begin) { 13 if(begin==buffer.length()-1){ 14 list.add(buffer.toString()); 15 } 16 for(int i = begin;i<buffer.length();i++){ 17 swap(begin,i); 18 PermutationCore(begin+1); 19 swap(begin,i); 20 } 21 } 22 public void swap(int i,int j){ 23 char a = buffer.charAt(i); 24 char b = buffer.charAt(j); 25 buffer.setCharAt(i, b); 26 buffer.setCharAt(j, a); 27 } 28 }
那么如何解决上面两点存在的问题呢?这里给推荐一种数据结构,TreeSet。 这个在C++中我不知道有没有,应该是没有,但是作为Java程序员,这是比较幸福的地方。
TreeSet这个数据结构本身采用红黑树实现,能够自动将字符串按照字典序排序,同时因为其实现了Set接口,所以又能同时保证所有的结果是一个集合。而学过离散数学的朋友都知道,集合中的元素是不会重复的,所以如果我们采用TreeSet对排列的结果进行存储,那么就能轻易的达到上述要求。下面是本人实现的代码:
1 import java.util.ArrayList; 2 import java.util.Iterator; 3 import java.util.List; 4 import java.util.Set; 5 import java.util.TreeSet; 6 public class Solution { 7 private List<String> list = new ArrayList<>(); 8 private Set<String> set = new TreeSet<>(); 9 private StringBuffer buffer; 10 public ArrayList<String> Permutation(String str) { 11 if(str==null||str.length()==0) return (ArrayList<String>) list; 12 buffer = new StringBuffer(str); 13 PermutationCore(0); 14 Iterator<String> iterator = set.iterator(); 15 while(iterator.hasNext()){ 16 list.add(iterator.next()); 17 } 18 return (ArrayList<String>) list; 19 } 20 public void PermutationCore(int begin) { 21 if(begin==buffer.length()-1){ 22 set.add(buffer.toString()); 23 } 24 for(int i = begin;i<buffer.length();i++){ 25 //if(buffer.charAt(i)==buffer.charAt(begin) && begin!=i) continue; 26 swap(begin,i); 27 PermutationCore(begin+1); 28 swap(begin,i); 29 } 30 } 31 public void swap(int i,int j){ 32 char a = buffer.charAt(i); 33 char b = buffer.charAt(j); 34 buffer.setCharAt(i, b); 35 buffer.setCharAt(j, a); 36 } 37 }
输入“abc” ,输出:"abc" "acb" "bac" "bca" "cab" "cba" ; 输入“aaa”,输出"aaa" ,显然符合要求了。
最后我们来看一看TreeSet的层次结构:
类似的结构还有ArrayList,LinkedList,HashSet,HashMap,TreeMap,PriorityQueue,Stack。另外重要的接口有:List,Set,Map,Queue,Deque,Comparator,Comparable,Itrerator。这些都是在编写数据结构和算法的时候经常用到的,尤其需要留意。