每天一道算法题——字符串的排列

字符串排列算法

前言:
这几天有点忙,这一个月没两天更新一次吧

题目描述
输入一个字符串,按字典序打印出该字符串中字符的所有排列。例如输入字符串abc,则打印出由字符a,b,c所能排列出来的所有字符串abc,acb,bac,bca,cab和cba。
测试用例:
abc
对应输出应该为:
[“abc”,”acb”,”bac”,”bca”,”cab”,”cba”]
错误的输出
[“bac”,”abc”,”acb”,”bca”,”cba”,”cab”]
没有进行排序,调用一下sort就好Collections.sort(list),不必要重新写一个函数吧,那就本末倒置了。
分析:
第一种使用递归的方法来解决此题。详情见代码。比较容易懂。
第二种方法是使用一个ArrayList将各个排列结果存放其中。首先将字符串分解为字符数组,然后从大到小进行排列后再对数组元素的值进行替换。直到形成最后的“最小的排列”,此时所有排列已经存储在了ArrayList之中了。返回ArrayList即可。称这种排列方式为字典排列。形如其名,就是按照词典排列的方式,将所有“词”无重复地录入到ArrayList这个“词典”当中。

源码:

递归的方法:


import java.util.ArrayList;
import java.util.Collections;

public class Test1 {
    public class Solution {
        public ArrayList<String> Permutation(String str) {
               ArrayList<String> list = new ArrayList<>();
               if (list!=null&&str.length()!=0) {
                Permutation(str.toCharArray(),0,list);
                Collections.sort(list);
            }
               return (ArrayList<String>) list;
        }

        private void Permutation(char[] charArray, int i, ArrayList<String> list) {
            if (i==charArray.length-1) {
                String  val = String.valueOf(charArray);
                if (!list.contains(val)) {
                    list.add(val);
                }
            }else {
                for (int j = 0; j < charArray.length; j++) {
                    swap(charArray,i,j);
                    Permutation(charArray, i+1, list);
                    swap(charArray,i,j);
                }
            }           
        }

        private void swap(char[] charArray, int i, int j) {
            char temp = charArray[i];
            charArray[i] = charArray[j];
            charArray[j] = temp;            
        }
    }
}

字典排列:

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;

public class Test1 {
    public class Solution {
        public ArrayList<String> Permutation(String str) {
            ArrayList<String> res = new ArrayList<>();
            if (str != null && str.length() > 0) {
                char[] seq = str.toCharArray();
                Arrays.sort(seq); // 排列
                res.add(String.valueOf(seq)); // 先输出一个解
                int len = seq.length;
                while (true) {
                    int p = len - 1, q;// 从后向前找一个seq[p - 1] < seq[p]
                    while (p >= 1 && seq[p - 1] >= seq[p])
                        --p;
                    if (p == 0)
                        break; // 已经是“最小”的排列,退出
                    // 从p向后找最后一个比seq[p]大的数
                    q = p;  
                    --p;
                    while (q < len && seq[q] > seq[p])
                        q++;
                    --q;// 交换这两个位置上的值
                    swap(seq, q, p);
                    // 将p之后的序列倒序排列
                    reverse(seq, p + 1);
                    res.add(String.valueOf(seq));
                }
            }
            return res;
        }
        public void reverse(char[] seq, int start) {
                int len;
                if(seq == null || (len = seq.length) <= start)
                    return;
                for (int i = 0; i < ((len - start) >> 1); i++) {
                    int p = start + i, q = len - 1 - i;
                    if (p != q)
                        swap(seq, p, q);
                    }
                }
        public void swap(char[] cs, int i, int j) {
            char temp = cs[i];
            cs[i] = cs[j];
            cs[j] = temp;
        }
    }
}

运行测试:

递归:运行时间:126ms 占用内存:13412k
字典排列:运行时间:96ms 占用内存:11864k

总结:
可以看到使用递归解决时还是占用相当多的资源的。所以如果需要做优化的话,可以将递归替换掉,虽然递归的条理更加清楚一点。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值