java - 求 char[] 的总唯一排列?

标签 java char permutation factorial

所以我正在开发一个小项目,我想编写一个方法来计算 char[] 的所有可能的唯一排列。其公式为

n!/ possible duplicates

意思是如果我有太妃糖这个词,它会是

6!/(2!*2!)

因为总共有 6 个字母,并且有 2 个重复的字母,每个字母都出现了两次。

我的第一个问题是似乎没有计算阶乘的标准方法。另外,我能想到的找出可能重复的唯一方法是扫描整个数组并跟踪每个字母出现的次数。有没有更好/更有效的方法来做到这一点?我所需要的只是返回一些可能的独特排列总数。

最佳答案

将数组转换为Set会删除重复项,但它不会告诉你删除了哪些重复项,所以它似乎别无选择,只能迭代数组并计算出现的次数每个字符:

private static Map<Character, Integer> countChars(char[] arr) {
    Map<Character, Integer> counts = new HashMap<>();
    for (char c : arr) {
        Integer count = counts.get(c);
        if (count == null) {
            count = 1;
        } else {
            count += 1;
        }
        counts.put(c, count);
    }
    return counts;
}

关于计算阶乘 - JDK 确实没有这样的工具。有几个第三方库提供它,例如 Apache Commons 的 CombinatoricsUtils ,或者您可以自己实现:

private static final long factorial (int i) {
    if (i == 0) {
        return 1L;
    }
    return i * factorial(i - 1);
}

然后,将它们放在一起:

private static long numPermutations(char[] arr) {
    long result = factorial(arr.length);
    Map<Character, Integer> counts = countChars(arr);
    for (Integer i : counts.values()) {
        // Note that 1! = 1
        result /= factorial(i);
    }
    return result;
}

编辑:
Java 8 的流式 API 为您提供了一种更优雅(或者至少更短。优雅实际上是见仁见智的问题)的实现 coutChars 的方法:

Map<Character, Long> counts = 
    new String(arr).chars()
                   .boxed()
                   .collect(Collectors.groupingBy(o -> (char) o.intValue(), 
                            Collectors.counting()));

关于java - 求 char[] 的总唯一排列?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32672475/

相关文章:

Java 比较两个地方的字符串并排除任何匹配项

java - 如何找到满足要求的最小操作集

java - 如何提高 Kabeja 生成的图像质量?

c++ - 计算排列的逆下降

java - Spring Boot 修改默认 JSON 响应

c++ - 写入文本文件,二进制与 ascii

java - 识别字符串中的特定字符并将其删除 - 不起作用

C#。为什么当我使用 TextReader.Read() 时它返回一个 int 值?可以转换为char吗?

java - 不同类型的多个列表的生成排列

c++ - 从非常大的范围返回非重复的随机值