我正在使用此代码https://stackoverflow.com/a/4240323/2655623来创建排列并对每个结果进行一些计算。
public static void permutation(String str) {
permutation("", str);
}
private static void permutation(String prefix, String str) {
int n = str.length();
int p = prefix.length();
if(p==5){
//do some calculation for |prefix| = 5
return;
}
for (int i = 0; i < n; i++){
permutation(prefix + str.charAt(i), str.substring(0, i) + str.substring(i+1, n));
}
}
这个算法对我很有用。但是,我想看看我如何删除重复的字符,所以我不再计算前缀。例如
permutation("aacccbbdeeeef");
我将处理 abcde 关于
A = 2 * 4*3*2*1 when a----
B = 2 * 4*3*2*1 when b----
C = 3 * 4*3*2*1 when c----
and so on...
// I hope you get the idea
我想知道我是否可以减少重复计算的数量。
我认为的一种方法是对字符顺序进行排序,并在我为其使用FOR时仅计算每个重复字符中的一个。
for (int i = 0; i < n; i++){
if(i>0 && str.charAt(i) == str.charAt(i-1)) continue;
permutation.....
}
这对我来说很好,因为只需要一次排列。当重复字母数很高时,它会大大减少调用次数。
现在,总结一下,我想知道是否
非常感谢。
答案 0 :(得分:2)
这是保证,我不会错过任何排列吗?
是。如果所有重复的字符都在块中,例如"aaabbccccc"
,那么代码行
if(i>0 && str.charAt(i) == str.charAt(i-1)) continue;
正是您所需要的。它不会错过任何排列,因为它只会跳过那些本来会相同的排列。并且它不会重复任何排列,因为相等的字符是块。
如何防止像(1)ba(2)cd和a(2)ba(1)cd这样的情况 当p = 5时发生。至于p = 8或10,我使用的技巧不会 那很有效率。那我需要做什么?
我认为不需要担心像"abacd"
这样的输入字符串。此字符串的排列集与"aabcd"
的集合完全相同,因此在开头对字符串进行排序是有意义的(这会将重复的字符收集到块中),并调用permutation("", sortedString);
。这样做你可以使用你提到的技巧。
对于长字符串,它总是很慢,因为有很多排列,也因为该方法创建了大量的字符串对象。这些因素更为重要,因为通过迭代比严格必要的范围稍大且使用continue
而产生的次要低效率。
答案 1 :(得分:0)
简单的解决方案是将字符存储到Set中(删除重复项)并读取它们;)
答案 2 :(得分:0)
public static void permutation(String str) {
Set<Character> charsSet = new HashSet<Character>();
for (int i = 0; i < s.length(); i++){
Character c = new Character (s.charAt(i));
charsSet.add(c);
}
StringBuilder sb = new StringBuilder();
for (Character c : charsSet) {
sb.append(c.charValue());
}
permutation("", sb.toString());
}
private static void permutation(String prefix, String str) {
int n = str.length();
int p = prefix.length();
if(p==5){
//do some calculation for |prefix| = 5
return;
}
for (int i = 0; i < n; i++){
permutation(prefix + str.charAt(i), str.substring(0, i) + str.substring(i+1, n));
}
}
答案 3 :(得分:0)
这是我的“长度为n的总有符号排列”的变体
样本数据集
2
示例输出
-1 -2
-1 2
1 -2
1 2
-2 -1
-2 1
2 -1
2 1
总计:8
请遵循以下示例:
private static int count = 0;
@Test
public void unsignedPermTest(){
final int unsigendN = 2;
final int n = unsigendN * 2;
final int[] arr = new int[n];
for(int i=1; i<=unsigendN;i++){
arr[i-1] = i;
arr[arr.length-i] = -i;
}
count = 0;
permutation(arr, n, unsigendN);
System.out.println("total: " + count);
}
public static void permutation(final int[] arr, final int n, final int k) {
permutation(arr, "", n, k);
}
private static void permutation(final int[] arr, final String prefix, final int n, final int k) {
if (k == 0)
{
final String res = prefix.substring(1);
final String[] chars = res.split(" ");
for(int i=0; i<chars.length;i++){
for(int j=i+1; j<chars.length;j++){
if(chars[i].replace("-", "").equals(chars[j].replace("-", ""))) return;
}
}
count=count+1;
System.out.println(res);
return;
}
for (int i = 0; i < n; ++i) {
permutation(arr, prefix + " " + arr[i], n, k - 1);
}
}