字符串的排列【Java版】

字符串的排列

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

输入一个字符串,按字典序打印出该字符串中字符的所有排列。例如输入字符串abc,则按字典序打印出由字符a,b,c所能排列出来的所有字符串abc,acb,bac,bca,cab和cba。
感谢牛客@LiuNing的图,来借用一下:

import java.util.ArrayList;
import java.util.Collections;
public class Solution {
    ArrayList<String> res = new ArrayList<String>();
    public ArrayList<String> Permutation(String str) {
        if(str == null || str.equals(""))return res;
        exchange(str.toCharArray(), 0);//【str==>char[]】  //String格式转化为char数组,方便交换操作
        Collections.sort(res);//最终输出前,要一次排序(字典序),不然每个人的答案不一样OG难以判断
        return res;
    }
    public void exchange(char [] ch, int left){//传ch[]是因为这个被递归改成无数个版本副本,而res只有唯一版本 所以提到外面
        if(left == ch.length-1){//left到了char[]数组的最后一个,才开始判重入列。否则长度不够的情况下都要继续向下分支
            if(!res.contains(new String(ch))){//由于输入的str可能有重复字母,所以要去重;否则按照这个算法,如果原str无重复是不需要去重的(每个都能用得上)
                res.add(new String(ch));//要new String对象 //看下还有没有别的方式??
            }
        }
        else{
            for(int right=left; right<=ch.length-1; ++right){//从j=i开始,意思是第一个交换是,保留原来的ch,而并不会真正交换
                swap(ch, left, right);
                exchange(ch, left+1);//深入
                swap(ch, right, left);//还原,for循环下一轮还要用 原始版的
            }
        }
    }
    public void swap(char [] ch, int i, int j){//swap不用返回,直接改ch[]
        char temp = ch[i];
        ch[i] = ch[j];
        ch[j] = temp;
    }
}
//【时间复杂度分析】
//下面的 N都是代表str的length, 比如 abc是3
//递归调用exchange()函数次数: N*(N-1)*(N-2)*...*1 = N!次
//判重:一共 N!次;每次的时间复杂度为O(N!) ==>因为要和res里面的所有str去比较
//综上,本题时间复杂度为 O(N!*N!)
//【空间复杂度分析】
//如果包括系统栈空间的话,每个递归exchange()函数都需要一个ch[],其大小为N
//那么总空间为:O(N!)*O(N) = O((N+1)!)
《剑指Offer-Java题解》 文章被收录于专栏

《剑指Offer-Java题解》

全部评论

相关推荐

1 收藏 评论
分享
牛客网
牛客企业服务