算法思考------字符串的全排列算法

5 篇文章 0 订阅
4 篇文章 0 订阅

相关题目:

牛客网 剑指Offer题:字符串的排列

题目描述:

输入一个字符串,按字典序打印出该字符串中字符的所有排列。例如输入字符串abc,则打印出由字符a,b,c所能排列出来的所有字符串abc,acb,bac,bca,cab和cba。
输入描述:
输入一个字符串,长度不超过9(可能有字符重复),字符只包括大小写字母。

全排列算法解决思路:

递归解决方式:

a b c 的全排列过程
这里以abc的全排列为例子,由图可以看出可以用DFS的思路解决,对可可选择的字母进行遍历,不断递归直到可选字母集合为空,此时就是一个排列顺序。

参考代码:

	private void Permutation(ArrayList<String> resList, StringBuilder sb, String str) {
        if (str.length() == 0) {
            resList.add(sb.toString());
        }
        else {
            for (int i = 0; i < str.length(); i++) {
            	String curValue = String.valueOf(str.charAt(i));
                sb.append(curValue);
                //这里是处理后面参数str拼接问题,要将已排序的数据移除
                if (i == 0) {
                    Permutation(resList, sb, str.substring(i+1));
                } else if (i == str.length() - 1) {
                    Permutation(resList, sb, str.substring(0, i));
                } else
                    Permutation(resList, sb, str.substring(0, i) + str.substring(i+1));
                //清除状态
                sb.deleteCharAt(sb.length()-1);
            }
       

测试结果:

测试结果
对于全排列还有另外一种,就是所要全排列的数据中有重复项,这样我们就需要在全排列前做一个判断,对于重复项,我们只对它们中的一个进行交换,即交换前先判断一下该数据后面是否有重复,如果有重复就跳过,只对最后面的那个进行全排,这样就可以避免重复了。

参考代码:

    private void Permutation(ArrayList<String> resList, StringBuilder sb, String str) {
        if (str.length() == 0) {
            resList.add(sb.toString());
        }
        else {
            for (int i = 0; i < str.length(); i++) {
            	//增加一个判断
                if (isChange(str, i)) {
                    String curValue = String.valueOf(str.charAt(i));
                    sb.append(curValue);
                    //这里是处理后面参数str拼接问题,要将已排序的数据移除
                    if (i == 0) {
                        Permutation(resList, sb, str.substring(i+1));
                    } else if (i == str.length() - 1) {
                        Permutation(resList, sb, str.substring(0, i));
                    } else
                        Permutation(resList, sb, str.substring(0, i) + str.substring(i+1));
                    //清除状态
                    sb.deleteCharAt(sb.length()-1);
                }
            }
        }
    }

    //判断要不要交换
    private boolean isChange(String str, int i) {
        //遍历后面看看有没有重复的,重复的话就不换了,多个重复只换一个就好
        for (int j = i + 1; j < str.length(); j++) {
            if (str.charAt(j) == str.charAt(i)) {
                return false;
            }
        }
        return true;
    }

测试结果:

测试结果
加了这个判断之后就可以对含有重复项的数据进行全排列啦

非递归解决方式:

TODO…

参考博客:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值