字谜算法返回重复值

Posted

技术标签:

【中文标题】字谜算法返回重复值【英文标题】:anagram algorithm is returning duplicate values 【发布时间】:2013-05-20 14:58:13 【问题描述】:

我一直在开发一种算法来计算给定(一组)单词的字谜。我刚刚让它工作,有一个令人难以置信的令人沮丧的异常(没有双关语;没有抛出实际的异常)。尽管我尝试利用有效的“修剪”来减少重复次数,我的算法正在向主列表添加重复项,在本例中是最终静态 ArrayList(StringBuilder)() 类型的对象。我似乎无法弄清楚为什么会这样。以下是我的代码;为了方便起见,我决定发布整个方法。

这是学校的作业,因此我正在寻找指导/概念上的错误,而不是直接的答案/解决方案。

编辑:(代码已被删除,以避免在作业截止日期之前可能出现抄袭。)

这是一个例子:

**input:**
pnxish
bauelqbs
coxiuqit
elbarcbs
ptos

**output:**
Now printing anagrams: 
Anagram #0: sphinx
Anagram #1: squabble
Anagram #2: squabble
Anagram #3: quixotic
Anagram #4: quixotic
Anagram #5: scrabble
Anagram #6: scrabble
Anagram #7: pots
Anagram #8: post
Anagram #9: tops
Anagram #10: opts
Anagram #11: spot
Anagram #12: stop

感谢您的帮助! :)

【问题讨论】:

你能给我们举个例子,输入、输出和预期输出吗? 习惯上写成 i 为什么要将 StringBuilders 添加到 anagramList 而不是 Strings? 是的,我刚刚编辑了一个 i/o 值的示例。谢谢你,很抱歉排除了那个重要的细节! 我正在使用 StringBuilders,因为它们是可变的;另一个原因是教授要求我们使用它们。 【参考方案1】:

显而易见的算法(只是交换字母)有点幼稚,并且不会将相同的字母视为相同字母的实例。例如,如果你有一个像“eve”这样的词,两个“e”是不同的;如果我们将第一个 E 加粗以进行说明,您会在过程中的各个点得到像“e v e”和“e v e”这样的组合。

您需要以某种方式消除重复项。最简单的方法是将组合填充到某种类型的 Set 中(如 HashSet)。它只能包含每个项目之一,因此重复项将被有效地丢弃。

哦,使用Strings,而不是StringBuilders。我刚刚注意到你正在这样做。 StringBuilder 不会覆盖 equals,因此您只剩下继承自 Object 的版本。最终结果:对于两个 StringBuilders aba.equals(b) 仅当 a == b

【讨论】:

我正在写一个答案,暗示只有当输入包含多个字符实例时才会重复:) 这就是问题所在!谢谢!我没有考虑重复的字母。【参考方案2】:

一个简单的解决方案是使用Set 来存储您的字谜。这将处理重复的值。

我的猜测是您使用的是列表,因为您的变量名为 anagramList。您可以在此处找到Set 的 JavaDoc:http://docs.oracle.com/javase/6/docs/api/java/util/Set.html

【讨论】:

您好,感谢您的回复!正如您在我的代码中看到的那样,在调用我的 ArrayList 的 add() 方法之前,我会检查以验证该值实际上没有被添加到列表中。因此,如果我正在执行检查,我仍然不确定重复项究竟是如何进入列表的。谢谢!【参考方案3】:

我希望使用 Set 来存储字谜,但使用 String 而不是 StringBuilder,即

Set<String> anagrams = new HashSet<String>();

不使用StringBuilder的原因是hashCode在改变的时候没有改变,如本例所示:

StringBuilder sb = new StringBuilder();
System.out.println(sb.hashCode());
sb.append('c');
System.out.println(sb.hashCode());

这将输出相同的哈希码,这意味着 StringBuilder 的哈希码对于其内容来说是不可靠的比较器。

【讨论】:

【参考方案4】:

这是您在代码中遇到的问题。如果您的列表中有一个 StringBuilder 对象用于“squabble”,当您再次构建“squabble”后检查列表是否包含“squabble”的不同 StringBuilder 对象时,contains 方法将返回 false(这是因为字母 b发生两次)。

包含检查对象是否在列表中,而不是检查是否存在表示相同字符串的对象。

【讨论】:

【参考方案5】:

不能使用 contains() 方法检查字符串内容本身是否在里面:

List<StringBuilder> list = new ArrayList<StringBuilder>();      
StringBuilder sb = new StringBuilder("hello");
list.add(sb);
StringBuilder sb2 = new StringBuilder("hello");
System.out.println(list.contains(sb2)); 
//echos false

【讨论】:

以上是关于字谜算法返回重复值的主要内容,如果未能解决你的问题,请参考以下文章

"==" 总是返回 true。字谜程序[重复]

查找单词字谜数量的算法?

字谜索引计算[重复]

没有重复的排列算法?

使用基本Java检查两个字符串是不是是彼此的字谜[重复]

算法:按字典顺序在给定索引处查找给定字符串的字谜