【问题标题】:Generate all permutations possible by deletion通过删除生成所有可能的排列
【发布时间】:2013-08-22 15:02:08
【问题描述】:

我需要通过删除字符串的一个或多个大字符来生成所有可能的唯一排列,而小字符应保持不变。

示例输入:

AalAADBdBBDkCeCCA

现在我需要生成所有可能的排列

  • 一次或多次删除一个 BIG 字符
  • 组合删除 1 到 n 个 BIG 字符,每个 BIG 字符删除 0 到 m 次(n = 输入中的直接字符数,m = 字符出现的次数)。
  • 保持小字符不变

我只对唯一的排列感兴趣,也就是说,如果第二个或第三个(固定!最初我写了第一个和第二个)A 被删除没有区别。当然,如果第一个或最后一个 A 被删除,它会有所不同。

排列示例:

AalAADBdBBDkCeCCA // original input also counts as permutation
AalAADBdBB kCeCCA // last D removed
 alAAD dBBDkCeCCA // first A and first B removed
Aal  D dBBDkCeC A  // second and third A removed, first B and last C removed

我正在使用番石榴,以防万一。一个普通的 Java 解决方案也可以。

如果有这种排列的名称和一些给出唯一排列总量的数学公式,我也会感兴趣,因此可以验证排列算法的结果(至少在正确的排列数量方面)。

这个例子是一个简化的问题,可以假设输入已经是一个字符列表或任何其他预解析格式,而不是一个合并的字符串。

感谢您对此的任何提示!

更新:

我想我找到了解决方案,欢迎反馈。 想法:提取每个大字符的索引(位置)。将它们放在一个集合中,创建该集合的幂集 P。这给出了可能删除的所有排列(包括重复,例如 1,2 和 2,1 以及如果 1 = 2 = 相同的 BIG 字符)

【问题讨论】:

  • 不确定我是否理解这一点:我只对独特的排列感兴趣,也就是说,如果删除第一个或第二个 A 没有区别。当然,如果第一个或最后一个 A 被删除,它会有所不同。 _alAADBdBBDkCeCCA 和 Aal_ADBdBBDkCeCCA 是相同的排列(只是对不重要的字符顺序感兴趣)还是不同?
  • @akaFlanners:对不起,我的错。在此示例中,删除第二个或第三个 A 没有区别,因为它们“站立”在一起(AA 之间没有任何东西)。关于您更新的评论:这两种排列是不同的。
  • 关于您的解决方案:您仍然需要过滤掉重复的字符串。您可以为此使用字符串集。但我想知道是否有更快的方法/更好的算法。 (有趣的问题+1)
  • 是的,我注意到了,我使用 Set 作为输出,所以没问题。目前我很幸运,这个问题可以减少另一个问题,所以至少编码它不是一个太大的问题。也想知道是否有更好的方法;-)

标签: java math guava permutation


【解决方案1】:

我对你的更新有一些类似的想法,但也许你最终会比我的更优雅,因为我没有过滤掉任何东西

我首先制作了一个包含字符串中所有大写字母的二进制表(我们可以忽略小写,因为它们永远不会被触及)。

从非常简单的示例开始,然后逐步进行。 在二进制表中,0 表示将字符留在原处,1 表示将其删除。

例如对于 A 的字符串(或任何只有 1 个大写字母的字符串,例如 aaaAa)2 个排列

A
0
1

对于 AB(或带有 2 个大写字母 aaaAaBbb 的字符串)4 个排列

AB
00
10
01
11

对于 ABC 8 排列

ABC
000
100
010
110
001
101
011
111

对于 ABCD 16 排列

ABCD
0000
1000
0100
1100
0010
1010
0110
1110
0001
1001
0101
1101
0011
1011
0111
1111

你会看到这些是 2^1, 2^2, 2^3, 2^4 2^numberOfUppercaseCharacters

这为您提供了总数排列,而无需删除重复问题。 您可以粗鲁地实现一种蛮力方法,该方法循环通过每个字符位置在字符处关闭 - 并将输出字符串保存到一个集合中。因为它在一个集合中,所以不会添加重复项。

所以把你的输入字符串 解析它以获取每个大写字符的索引

在上面的二进制表中,从概念上考虑将 A B C 替换为字符串中的索引位置。

所以

对于字符串 aaAbbBb,我们有索引 2 和 5(基于 0 的索引)

A B
_ _
0 0
1 0
0 1
1 1

变成

2 5
_ _
0 0
1 0
0 1
1 1

因此,如果我们采用最多 2^numOfUppercase 的二进制数表示并删除应该起作用的关联值。注意下面的示例具有硬编码的字符串和大写索引列表。至少你有一些东西可以尝试检查你的解决方案。

注意不知道这种方法的上限 - 很可能会因为大写字符的长字符串作为排列的大二进制表示而失败。

这里的示例:

import java.math.BigInteger;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Set;


public class StringProcessing {


public static void main(String[] args) {
    // TODO Auto-generated method stub
    StringProcessing sp = new StringProcessing();
    sp.setUpProcessing();

}

public void setUpProcessing() {
    String input = "aaABCDcs";

    //Populate with indexes of Uppercase letters (loop though each char and check if [A-Z])
    ArrayList<Integer> indexes = new ArrayList<Integer>();
    indexes.add(2);
    indexes.add(3);
    indexes.add(4);
    indexes.add(5);

    Set<String> permutationStore = new HashSet<String>();
    BigInteger permutations = BigInteger.valueOf(2).pow(indexes.size());  //2^numOfUppercaseChars


    int maxSize = getMaxLength(permutations); //Need this for padding binary with 0

    for (BigInteger index = BigInteger.ZERO; index.compareTo(permutations) < 0;  index = index.add(BigInteger.ONE)) {
        String binary = index.toString(2);
       // System.out.println(permutations + " " + index + " " + binary + ", for string: " + input); //NumOf Permutations, currentPermutation, binaryRepresentation

        int lastIndex = binary.length() -1;
        StringBuilder currentString = new StringBuilder(input);
        String permutationString = process(lastIndex, binary, currentString, indexes, maxSize);
        permutationStore.add(permutationString);
        System.out.println(permutations + " " + index + "    " + binary + ", for string: " + input + ", Stored: " + permutationString);
    }

    System.out.println("");
    for(String s : permutationStore) {
        System.out.println(s);
    }

}

public int getMaxLength(BigInteger permutations) {
   BigInteger zeroBased = permutations.subtract(BigInteger.ONE);
   return  zeroBased.toString(2).length();
}

public String process(int lastIndex, String binary, StringBuilder currentString, ArrayList<Integer> indexes, int maxSize) {
    int indexFound = binary.lastIndexOf('1', lastIndex);

    if (indexFound == -1) {
        return currentString.toString();
    }
    int padding =  maxSize - binary.length(); //Add leading "0's" to binary 

    int index = indexFound + padding;
    int charPos = indexes.get(index);

    currentString.deleteCharAt(charPos);
    process(indexFound-1, binary, currentString, indexes, maxSize);

    return currentString.toString();
}

}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-05-05
    • 2016-09-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多