字符串的排列

输入一个字符串,按字典序打印出该字符串中字符的所有排列

Posted by DH on July 6, 2017

题目

输入一个字符串,按字典序打印出该字符串中字符的所有排列。例如输入字符串abc,则打印出由字符a,b,c所能排列出来的所有字符串abc,acb,bac,bca,cab和cba。

要求

输入一个字符串,长度不超过9(可能有字符重复),字符只包括大小写字母。

分析

假如我们固定第一个字母,然后依次将第一个字母依次与子串中的其他字母进行交换。也就是固定第一个字母,只需要求出后面子串的排列个数就可以得到结果,因此考虑使用递归算法。递归的出口就是只剩下一个字符的时候。

但是,有一个问题是,加入字符串中有重复的字符,此时会得到重复的结果。

  • 思考一

如果一个数与后面的数字相同那么就不进行交换。例如abb,a与第一个b交换得到bab,a与第二个b交换的到bba,这是时候,交换b的结果是abb,所以第二个字符与第三个字符不用交换。但是,字符串是bab,第二个字符和第三个字符不一样,需要交换,因此这个思考行不通。

  • 思考二

abb,第一个字符a与第二个字符b交换得到bab,然后考虑第一个字符与第三个字符交换,假如第三个数等于第二个数,第一个数就不再用与第三个数交换了。假如,第二个字符与第三个字符不相同,则进行交换。全排列完成!     abc的递归过程如下图所示:

代码

综上分析,代码如下:

	import java.util.ArrayList;
	import java.util.Collections;

	public class Solution {
   	 public ArrayList<String> Permutation(String str) {
       
        	ArrayList <String> result = new ArrayList<String>();
        	// 字符串为空或者长度为0
       	 	if(str == null || str.length() == 0)
        	{
   	         	return result;
        	}
        
        	// 将字符串转化为字符数组
        	char[]chars = str.toCharArray();
        
        	getResult(chars,0,str.length() - 1,result);
        
        	Collections.sort(result);
       
        	return result;
        
    	}
    
    	public void getResult(char[] chars,int start,int end,ArrayList <String> result){
        	if(start == end){
            		result.add(new String(chars));
        	}else{
        
        		for(int i = start; i < chars.length; i++){
                
                		if(i == start || chars[start] != chars[i]){
                    
            			swap(start,i,chars);
                
                		getResult(chars,start + 1,end,result);
                
               			swap(start,i,chars);
                	}
        	}
        }
    }
    
   	 public void swap(int i ,int j, char[] chars){
        	char temp = chars[i];
       		chars[i] = chars[j];
        	chars[j] = temp;
    		}
}

需要注意的是: Collections.sort(result); 有的平台少了这句,是不能通过的,这句代码的意思是对得到的list进行排序,默认是按照首字母升序排列的。