面试题38. 字符串的排列《剑指offer(第二版)》

题目

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

 

你可以以任意顺序返回这个字符串数组,但里面不能有重复元素。

 

示例:

输入:s = "abc"
输出:["abc","acb","bac","bca","cab","cba"]

题解1:基于选择的排列

思路:

多次对字符串进行遍历,用StringBuffer来存储选择的字符,每次对于每个字符都可以选择加入或者不加入StringBuffer,直到字符串中所有字符都被遍历一次,则生成的StringBuffer为一个原字符串的一个排列,并使用HashSet来去重(防止字符串中有重复字符)

缺点:时间复杂度很高,每次dfs都是s.length()-1次循环,并且每次递归都得使用新的StringBuffer,采用的是先获取字符串排列再去重。

代码:

class Solution {
    public String[] permutation(String s) {
        set = new HashSet();
        char[] c = s.toCharArray();
        boolean[] visited = new boolean[s.length()];
        dfs(c,visited,new StringBuffer());
        return set.toArray(new String[set.size()]);
        
    }

    public Set set = null;

    public void dfs(char[] c,boolean[] visited,StringBuffer sb){
        boolean flag = false;
        for(int i=0;i

题解2:基于交换的排列(参考leetcode他人的解答)

思路:每次都对一组字符进行交换,dfs中for遍历每次都选择一个后边的元素与当前元素做交换。另外使用一个大小为256的boolean数组来去重(这是由于考虑到ascii的取值范围为0~255)。

优点:遍历次数比上边少,基于交换,所以不需要额外空间来保存特定字符串排列的状态,另外采用ascii表直接在获取排列的阶段完成去重。

代码:

class Solution {
    ArrayList res = new ArrayList<>();
    public String[] permutation(String s) {
        char[] ch = s.toCharArray();
        dfs(ch,0);
        String[] str = new String[res.size()];
        if(s == null || s.length() == 0) return str;
        for(int i = 0; i < res.size(); i++) {
            str[i] = res.get(i);
        } 
        return str;
    }
    private void dfs(char[] ch, int start) {
        if(start == ch.length) {
            res.add(new String(ch));
            return;
        }
        boolean[] used = new boolean[256];
        for(int i = start; i < ch.length; i++) {
            if(used[ch[i]]) continue;
            used[ch[i]] = true;
            swap(ch,start,i);
            dfs(ch,start+1);
            swap(ch,start,i);
        } 
    }
    private void swap(char[] ch, int i, int j) {
        char tmp = ch[i];
        ch[i] = ch[j];
        ch[j] = tmp;
    }
}

 

你可能感兴趣的:(leetcode)