【问题标题】:Optimized Algorithm for finding permutation of a given String?用于查找给定字符串排列的优化算法?
【发布时间】:2013-12-12 13:17:02
【问题描述】:

在下面的代码中,我找到了给定输入字符串的所有可能排列并将它们存储在一个列表中,然后计算其中的回文数。当输入字符串长度小于 10 时,这工作正常。但是当输入字符串长度大于 10 需要很长时间才能找到排列。我想知道这里可以优化什么以获得恒定的执行时间?

private static char[] inputArray;
private static List<String> listOfpermutations = new ArrayList<>();
private static int count;

public static void main(String s[]) throws IOException {
    BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
    String input = reader.readLine();
    inputArray = input.toCharArray();
    permutation(0);
    for (String combination : listOfpermutations) {
        if (combination.equals(new StringBuilder(combination).reverse().toString())) {
            count++;
        }
    }
    System.out.println(count);
}

public static void permutation(int start) 
{
    String temp = "";
    if (start != 0) {
        if (start == inputArray.length) {
            for (int i = 0; i < start; i++) {
                temp = temp + inputArray[i];
            }
            if (!listOfpermutations.contains(temp)) {
                listOfpermutations.add(temp);
            }
        }

    }
    for (int i = start; i < inputArray.length; i++) 
    {
        swap(start, i);
        permutation(start + 1);
        swap(start, i);
    }
}

static void swap(int pos1, int pos2) {
    char temp = inputArray[pos1];
    inputArray[pos1] = inputArray[pos2];
    inputArray[pos2] = temp;
}

测试输入:

  1. aaabbb //效果很好
  2. ccccddddcc //工作正常
  3. ccccdddddcce //这里的时间太长了

【问题讨论】:

  • 你同时使用循环和递归......你应该尽量避免......
  • 很确定恒定时间是不可能的。
  • 不可能持续执行,因为你试图生成 n!排列。执行时间总是随着 n 增长。
  • @DanglingPiyush - 使用不同的数据结构只会改变常量值......它可能会有所帮助,但不会产生重大影响......

标签: java algorithm optimization permutation


【解决方案1】:

IMO 这更像是一道数学题,而不是算法题。

由于您只对回文字符串的数量感兴趣,因此您不需要生成所有可能的排列。

计算字符串中每种类型的字符数。将字符除以二。计算该半串的排列数。这将是答案,因为字符串的另一半只是反映了这一半。

例如,如果字符串是 aabbcc,则 a 的计数 = 2,b 的计数 = 2,c 的计数 = 2。

所以我们将它们减半以形成 abc,以 6 种方式排列。这将是回文的排列数。

(你需要检查字符串中的字符数是奇数还是偶数)

【讨论】:

  • 每一种String是什么意思?
  • 字符串中每种类型的字符。例如,如果字符串是 aaabbbccc,则 a 的计数 = 3,b 的计数 = 3,c 的计数 = 3。
  • 很棒的计划!!但我会在完成后立即实施并接受您的回答。非常感谢。
【解决方案2】:

您可以在不生成所有 n 的运行时间上获得显着改善!排列。

由于您要查找回文,因此您的输入数据预计会包含许多重复的字符。生成排列的方式将生成许多相同的排列。 (作为副作用,您将多次计算某些排列)。

相反,在lexicographic order 中生成排列

PS。此外,您可以跳过创建完整列表,而只需在生成下一个排列后立即检查回文。

PPS。 Abhishek Bansal 的想法确实不错。

计算字符串中每个字符出现的次数。如果回文是可能的, 那么所有字符都必须有偶数,也许只有一个。

将每个计数除以 2,并在除法后按字母顺序创建一个具有该计数的字符串。例如,从 "abcccabaa" 你得到字符串 "aabc" (注意c 有奇数并且它在新字符串中出现一次)。

从结果字符串中,按字典顺序生成并计算所有排列。 这将是你的答案。您不需要检查回文,因为您可以通过这种方式生成所有可能的回文。每个这样的排列将代表回文的一半。整个回文将是前半部分,后面可能是奇数字符的单个实例,然后是反转的前半部分。例如,前几个回文将是

"aabc" + "c" + "cbaa"
"aacb" + "c" + "bcaa"
"abac" + "c" + "caba"

【讨论】:

  • 听从了您立即检查回文的建议。这大大减少了执行时间。将尝试执行您建议的字典顺序。感谢您的快速回复。
【解决方案3】:

几个性能提示:

  • 确定列表的大小并将该大小作为构造函数的一部分传递。您花费大量时间来扩充列表。
  • 根本不要使用列表。只需在构造排列时确定排列是否为回文即可。
  • 尝试创建独特的排列,然后从排列中创建回文(例如,“abac”会给出“abacaba”)。这应该会为您提供与现在相同的设置。

【讨论】:

    【解决方案4】:

    有一种更好的方法可以做到这一点,这将在很大程度上降低您的时间复杂度。

    实施步骤:-

    1. 首先将您的字符串压缩为压缩形式。 例如 aaabbb 简化为 a3b3。 ccccddddcc 简化为 c6d4。
    2. 接下来如果字符串的长度是偶数,那么每个字符的计数(频率)必须是偶数。如果每个字符都没有计数,那么它的回文排列为零。 而且,如果字符串的长度是奇数,那么它们必须恰好是一个奇数(频率)的字符。如果至多一个元素没有奇数,那么它的回文排列为零。 例如,aaabbb
      字符串长度 - 6(偶数)
      但是字符 'a' 和 'b' 有奇数。
      因此,它具有零回文排列。

      例如ccccddddcc
      字符串长度 - 10(偶数)
      所有字符“c”和“d”都有偶数。
      因此,它具有回文排列。

      例如ccccd
      字符串长度 - 5(奇数)
      'c' 的计数为 4(偶数),而 'd' 的计数为奇数,即 1
      因此,它具有回文排列。

    3. 现在,在第二点你必须知道字符串是否有回文排列,现在我们只需要找出有多少排列。

    4. 当字符串被简化为 c6d4 这样的格式并且你知道它存在排列时,你可以像这里一样继续:

      例如c4d2 take 可以减少到 3 个字符(如 2c 和 1d,因为在回文中其余字符串相同)以及如何排列它们, 所以答案是 3!/(2!*1!) = 3

      例如c4e4d1 可以减少到 4 个字符(如 2c 和 2e,因为在回文中其余字符串是相同的,而 1d 字符会介于两者之间),所以答案是 4!/(2!*2!) = 6。

    【讨论】:

    • 它对 aaabbbb 有问题,你能在第四点解释这个字符串将如何得到解决吗?在我的例子中,它给出 1 作为答案,但它应该给出 3。
    • @DanglingPiyush 字符串 aaabbbb 将被缩减为 a3b4,因此我们可以将字符串缩减为 2b 和 1a,因为要使字符串成为回文,字符串的其余部分应该与最初的相反一半,所以如果你要寻找它的排列,它将是 3!/(2!*1!) = 3。
    猜你喜欢
    • 2021-11-08
    • 1970-01-01
    • 2017-05-26
    • 1970-01-01
    • 1970-01-01
    • 2011-07-05
    • 1970-01-01
    • 2015-02-13
    • 1970-01-01
    相关资源
    最近更新 更多