您的位置:首页 > Web前端

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

2018-03-30 23:13 204 查看
前言:

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

题目描述

输入一个字符串,按字典序打印出该字符串中字符的所有排列。例如输入字符串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

总结:

可以看到使用递归解决时还是占用相当多的资源的。所以如果需要做优化的话,可以将递归替换掉,虽然递归的条理更加清楚一点。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息