题解 | #字符串的排列#

字符串的排列

http://www.nowcoder.com/practice/fe6b651b66ae47d7acce78ffdd9a96c7

字符串的排列

题目

输入一个长度为 n 字符串,打印出该字符串中字符的所有排列,你可以以任意顺序返回这个字符串数组。例如输入字符串abc,则输出由字符a,b,c所能排列出来的所有字符串abc,acb,bac,bca,cab和cba。

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

分析

我这里采用递归的方式去试试,思路便参照普通列举的思路。 <!- 我希望像我这样的小白也能看懂 ->

先不考虑去重。 记 长度 length, 从第一个位置0开始,有length个字符选择,后面位置依次可选择的字符数依次递减,因此便考虑每选择一个位置的字符后,下一个位置的字符便从剩下的字符串里选择,这里便是递归。递归出口在,每一次把所有位置的字符选择了后,位置便到了length处,这里就将前面的字符串放进Map里,不存在则放进去。

最后将Map 里的Key拿出来,便去重了,返回即可。

以下的代码参考前人大佬的思路。

特便是那个递归与for循环的结合,真是妙啊。

代码

import java.util.*;
public class Solution {

    //小白也也能快速看懂的递归法
    
    int length=0;
    char [] arry; //以数组形式保存,方便理解    
    HashMap<String,Integer> list =new HashMap<>(); //list 保存初始的字符串  
    
    public ArrayList<String> Permutation(String str) { 
        
        arry = str.toCharArray();//工具类转换
        length=str.length();//获取长度
        
        //Arrays.sort(arry); //后面用HashMap得到key值,就不用排序,去重
        //System.out.println(arry);
        
        int k = 0;  //这个很重要,表示当前位置的字符选择。
        ArrayList<Character> arrycopy = new ArrayList<Character>(); //复制一份,因为后面用的是改变了arry,将arry用作了要保存的值。
        
        for(char a:arry){
            arrycopy.add(a);//常规复制,
        }
        //System.out.println(arrycopy);
        
        collect(arrycopy,k);  //collect 表示选择当前k位置的字符,从0开始,如果==length,表示这一次的位置上都选择了,一次完成。

        HashSet hs = new HashSet(list.keySet()); //这里用Map集合的key值拿到,即去重了,然后返回了一个set集合。
        
        ArrayList<String> res=new ArrayList<>(hs);//res 表示要保存返回的结果。
        
        return res;  
        
    }
    
    //collect 函数,
    /**
    *arrytemp 表示要在当前里的选择字符的数组
    *k 表示当前要选择字符的位置
    *
    */
    public void collect(ArrayList<Character>  arrytemp,int k){
        //如果一次的字符选择完,则选择完毕,进去查重
        if(k==length){
            String s=new String(arry);//数组转换为字符串
            if(!list.containsKey(s)){
                // 如果不存在,才添加进来。
                list.put(s,1);
            }
        }else{
            for(int i=0;i<arrytemp.size();i++){
                //这里开始,arry 表示的要生成的数组,所以,我们要将每一次arrytemp对应位置的值得到,
                //并去除已经选择了的字符,传给下一次选择
                arry[k]=arrytemp.get(i);  //选择当前位置
                ArrayList<Character> arrytemp2=new ArrayList<>(arrytemp);  //生成新的要选择的字符串
                arrytemp2.remove(i);  //去掉已经选择的字符,
                
                collect(arrytemp2,k+1); //从已经去掉选择当前字符的字符串选择下一位字符
            }
        }

    }
    
}

时间空间复杂度分析

时间复杂度:O(n!) 空间负责都:O(n !)

全部评论

相关推荐

况世奇才:我七月投的Java,面试官说搞大数据的,挂个Java的吸引进来投简历的,已经offer评估了看看能不能泡出来吧
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务