我接受过关于字谜的练习,看起来很容易让我怀疑我错过了什么。 我实施的解决方案是我即将提出的解决方案,我想问你是否可以考虑使用我的解决方案进行任何优化,改变方法或问题。 我用Java实现了算法。
现在,练习。 作为输入我有一个文本作为输出我应该返回这个文本的每一行是否是每一行的一个字谜。 也就是说,输入:
出租车契约最疯狂的Min鱼L .. 驾驶室契约最疯狂的Min鱼L 驾驶室契约洗牌百万不会 驾驶室契约洗牌百万镇
程序应该返回True。 输入:
出租车契约最疯狂的Min鱼L .. 驾驶室契约最凶小的鲤鱼Lolls喜 驾驶室契约洗牌百万不会 驾驶室契约洗牌百万镇
输出必须为False(当然,因为第二行)。
现在,我认为非常简单:
而且......就是这样。 我尝试使用88000行的输入文本,它的工作速度非常快。
有何评论?建议?优化
非常感谢您的帮助。
答案 0 :(得分:5)
另一种选择是:
.equals
)我怀疑你的方式更快。</ p>
编辑:
因为@nibot不同意我甚至暗示这一点,并且我不是一个没有证据来回争辩的人,here's three solutions。
它们的实施非常相似:
?部分是以下之一:
HashMap
字符数我用它来运行它们:
public static void time(String name, int repetitions, Function function,
int expectedResult) throws Exception {
long total = 0;
for (int i = 0; i < repetitions; i++) {
System.gc();
long start = System.currentTimeMillis();
int result = function.call();
long end = System.currentTimeMillis();
if (result != expectedResult) {
System.out.println("Oops, " + name + " is broken");
return;
}
total += end - start;
}
System.out.println("Executution of " + name + " took "
+ (total / repetitions) + " ms on average");
}
我的文件类似于OP发布的文件,但是显着更长,从最后使用非anagram大约20行,以确保算法都能正常工作。
我一直得到这样的结果:
Execution of testWithHashMap took 158 ms on average
Execution of testWithSorting took 76 ms on average
Execution of testWithArray took 56 ms on average
如果符合以下条件,HashMap
可能会得到显着改善:
HashMap<char, int>
HashMap
中的默认值以及获取和增加的方式(因此只有一次查找而不是2次)但是,这些不在标准库中,所以我忽略了它们(就像大多数使用Java的程序员一样)。
故事的寓意是大O不是一切。您需要考虑 n 的开销和大小。在这种情况下, n 相当小,HashMap
的开销很大。如果线条较长,可能会发生变化,但不幸的是,我不想找出收支平衡点的位置。
如果您仍然不相信我,请考虑GCC在其C ++标准库中使用 insertion sort 。
答案 1 :(得分:3)
假设您的HashMap是来自(字符)的映射 - &gt; (字符串中出现的次数),你几乎拥有它。
我认为你应该忽略空格和标点符号,并将大写和小写字母视为相同。如果你没有使用除英语以外的任何语言,那么HashMap就是过度杀戮:你可以简单地使用一个包含A..Z的26个数组。如果你需要支持Unicode那么问题当然要复杂得多,因为你不仅需要处理数千种不同类型的字母,而且你还必须定义'字母'(幸运的是存在字符属性数据,帮助这个)和'小写/大写'(请注意,有些语言没有大小写,有些语言可以将两个小写字母映射为单个大写字母,反之亦然......)。更不用说正常化了:))
答案 2 :(得分:2)
建立@Karl Knechtel的答案(并解决您对支持多个字母表的担忧):
创建接口(比方说)AnagramKey和AnagramKeyFactory。将应用程序的其余部分设计为与所使用的密钥类型无关。
创建一个AnagramKey接口的实现,该接口在内部使用int[]
来表示字符数。
创建AnagramKey接口的第二个实现,它使用HashMap<Character, Integer>
来表示字符数。
创建相应的工厂接口。
使用命令行参数,区域设置或其他方式在两种表示键的方式之间进行选择。
注意:
目前尚不清楚“字谜”在非字母语言的背景下是有意义的,还是将多种语言混合成“句子”的话语。另外,我不知道(例如)法语中的字谜是否忽略了字符的重音。无论如何,我很想把所有这些案件都排除在“超出范围”之外......除非你明确要求支持它们。
int[]
使用的空间小于HashMap<Character, Integer>
的均衡密度在计数数组中的字符范围内渐近约为15个字符。 (具有这些键/值类型的HashMap中的每个条目占用15个32位字的区域。)并且没有考虑HashMap
节点和散列数组节点的开销......
如果您对字谜的长度设置限制,则可以使用short[]
甚至byte[]
来保存更多空间。