【问题标题】:Anagram Algorithm ClarificationAnagram 算法说明
【发布时间】:2015-07-18 09:12:00
【问题描述】:

我是这个论坛的新手,想问一个问题。我见过很多人就字谜提问,但我的问题与这个特定的算法有关。我看到这个算法使用递归技术来生成字谜,但该算法的一部分对我来说不是很清楚。我想就为什么要采取这一特定步骤寻求帮助。该算法大纲来自 Programming Interview Exposed。这是算法:

如果你超过了最后一个位置
打印字符串并返回
否则
对于输入字符串中的每个字母
如果标记为已使用,请跳至下一个字母
否则将字母放在当前位置
- 标记使用的字母
- 置换盯着当前位置的剩余字母+1
- 将信件标记为未使用

这是相同的代码:

void permute(String str){
    int length = str.length();
    boolean[] used = new boolean[length];
    StringBuffer out = new StringBuffer();
    char[] in = str.toCharArray();
    doPermute(in, out, used, length, 0);
}
void doPermute(char[] in, StringBuffer out, boolean[] used, int length,
    int level){
    if (level == length){
        System.out.println(out.toString());
        return;
    }
    for (int i = 0; i<length; i++){
        if (used[i]) continue;
        out.append(in[i]);
        used[i] = true;
        doPermute(in, out, used, length, level + 1);
        used[i] = false;
        out.setLength(out.length() - 1); // why are we reducing the size of out??
    }
}

代码解释中提到,当递归调用返回时,只是通过减小缓冲区大小来丢弃最后一个字符。我无法理解为什么我们要删除最后一个字符?有人可以请指导。谢谢!!!!!!

【问题讨论】:

  • 哇,这个算法比我以前看到的字谜检查要复杂得多。我习惯看到“将两个单词拆分为字母并对其进行排序,如果结果匹配,则两者是字谜”。
  • 我认为这是字谜生成算法而不是检查:)

标签: java algorithm anagram


【解决方案1】:

恢复out.append(in[i]);(添加一个字符)的效果,并在每次循环for 循环后将缓冲区恢复到相同的状态。

for (int i = 0; i<length; i++){
    if (used[i]) continue;
    out.append(in[i]); // try adding the ith letter
    used[i] = true;    // and mark it as used
    doPermute(in, out, used, length, level + 1); // do all the permutations for the remaining letters
    used[i] = false;                 // undo what we did
    out.setLength(out.length() - 1); // at the start of the loop
}

就这么简单。

【讨论】:

  • 感谢 biziclop!假设我有字符串 abc,我需要为它获取字谜。所以这里是递归调用——对于从 a 开始的字谜,我们得到 3 个递归调用:doPermute(in, out,3,1), dopermute(in, out,3,2), doPermute(in,out,3,3 )。当长度和级别变为它时,递归调用返回,现在每个字符都被标记为未使用,并且该字符的输出缓冲区被清除,直到第一次递归调用,即执行 permute(in, out,3,1)。然后我们将从 b 开始 anagram 并将使用已清除的相同缓冲区。这是正确的还是遗漏了什么?
【解决方案2】:

该算法正在执行以下操作:

  • 从所有字母的集合中,我们选择起始字母。
  • 如果我们都设置好了,那么我们打印一个可能的字谜。
  • 否则,我们将其标记为已使用,我们需要将剩余字母的排列添加到末尾。

让我们在这里举个例子:

我们收到以下信函:

e, x, a, m, p, l, e

让我们选择第一个字母:

两者之一:

  • example 的可能排列之一,
  • xeample 的可能排列之一

当我们选择所有皮革时,我们将打印创建的单词。

您也可以将其视为决策树, 首先,您选择 n 个字母中的一个,然后从剩余的字母中选择一个,一旦您选择了所有字母(您到达树的底部并获得了一个独特的字谜),因为在每一步中您都有一个 for 循环(因此对于所有可能的决策,请探索树的较低级别)您将获得每个组合并打印它。

我真的希望这会有所帮助。

【讨论】:

    猜你喜欢
    • 2012-03-08
    • 2017-10-28
    • 2017-06-14
    • 1970-01-01
    • 2012-12-04
    • 1970-01-01
    • 1970-01-01
    • 2014-02-03
    • 2015-06-08
    相关资源
    最近更新 更多