剑指38—字符串的排列

剑指38—字符串的排列

题目

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

思路

  1. 有要求排序,则需要将字符串所有字符取出生成等长的char数组并进行排序,再根据排序后的结果选择字符进行组合;
  2. 选择字符的过程可以用递归实现,使用for循环进行递归调用也可以满足字典序进行组合,那么这个过程中需要有一个boolean数组来标志该字符是否已被使用;
  3. 递归终止条件设置为当前组合的字符串长度等于char数组的长度;
  4. 递归体中使用一个for循环,从排好序的char数组的第一位开始进行遍历与组合可以保证字典序。首先应该查询该位是否使用过,已使用则跳过该字符去遍历下一个字符,未使用则更新使用状态为使用(true),然后将该字符加入组合的串中,接着递归调用。待递归返回后,从串中删除该字符,将使用状态更新为未使用(false),达到回溯。

代码

private ArrayList<String> ret = new ArrayList<>();

public ArrayList<String> solute(String str){
    if (str.length()==0) {
        return ret;
    }
    char[] chars = str.toCharArray();
    Arrays.sort(chars);
    back(chars,new boolean[chars.length],new StringBuilder());
    return ret;
}

//hasUsed存储对应位置的字符使用情况,s存储当前组合方案
private void back(char[] chars,boolean[] hasUsed,StringBuilder s){
    //完成组合时返回
    if(chars.length==s.length()){
        //这里需要创建一个新的String对象,
        //也可以使用s.toString()
        ret.add(new String(s));
        return;
    }
    //for循环保证按照字典序遍历组合
    for (int i=0;i<chars.length;i++) {
        //当前字符已被使用则跳过
        if(hasUsed[i])
            continue;
        //保证位置靠前的重复字符被优先使用
        if(i!=0&&chars[i]==chars[i-1]&&!hasUsed[i-1])
            continue;
        hasUsed[i] = true;
        s.append(chars[i]);
        //递归调用,此时hasUsed和s都是被更新了的
        back(chars,hasUsed,s);
        //递归调用返回后,进行回溯
        s.deleteCharAt(s.length()-1);
        hasUsed[i] = false;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值