样本'C'挑战的方法

时间:2012-06-07 20:58:46

标签: c algorithm data-structures

我最近被问到一个理论上的C问题,我想知道最好的方法是什么:

如果我有一个包含10个单词的文档,那么确定是否有重复单词的最佳方法是什么?如果有重复单词,我将如何跟踪有多少单词?

任何有关如何处理此问题的见解都会很棒。

5 个答案:

答案 0 :(得分:5)

关键字是“十”:这意味着最简单的方法,两个嵌套循环在它前面检查每个单词将会很好。如果数字是10000000,那么保证使用散列表,堆或排序数组的方法。但是,只有十个单词,您不需要构建任何复杂的东西 - 只需要基本的C字符串读取/比较知识。

答案 1 :(得分:2)

像这样的理论面试问题总是少量(如10个单词)。但是,这个数字没什么意义;它可以将那些真正能够在一般形式中解决问题的候选人与那些只是简单地回归他们在互联网上找到的固定面试问题的人进行分离。

最好的软件公司只会支持可扩展的解决方案。因此,如果您的答案很简单,您可以在面试中获得最高分,但也可以扩展到任何规模的问题(或者,在这种情况下,文档)。因此,排序,循环内部循环,O(n ^ 2)复杂性,忘记它们。如果你在面试时向一家领先的软件公司提出这样的解决方案,你就会失败。

您的具体问题是检查您是否了解哈希表。解决此问题的最有效方法可以用伪代码编写,如下所示:

1. Initialise a new hash table.
   For each word in the document...
2.     Generate a hash key for the word.
3.     Lookup the word in the hash table using the key. If it is found,
4.         Increment the count for the word.
       Otherwise,
5.         Store the new word in table and set its count to one.


上述解决方案的最重要的好处只需要对文档进行一次扫描。没有读入内存然后处理(两次扫描),循环中没有循环(许多扫描),没有排序(甚至更多次通过)。在完成一次文档传递后,如果您读出哈希表中的键,则每个单词的计数会准确地告诉您每个单词在文档中出现的次数。任何计数大于1的单词都是重复的。

此解决方案的秘诀在于使用哈希表。散列密钥(步骤2),密钥查找(步骤3)和密钥存储(步骤5)的生成可以实现为接近恒定时间操作。这意味着随着输入集的大小(即单词数量)的增长,这些步骤几乎不会改变的时间。这意味着无论是文档中的第10个单词,还是第1000个单词,将该单词插入哈希表(或查找它)将花费大致相同的非常小的时间。在这种情况下,我们还在步骤5中保留每个字的频率计数。增加一个值是一个非常有效的固定时间操作。

此问题的任何解决方案必须至少扫描一次文档中的所有单词。由于我们的解决方案一次处理完全的每个单词,所有单词处理大致相同的非常小的恒定时间,我们说我们的解决方案执行最佳并且线性,产生 O(n)性能(简单地说,处理1,000,000个单词比处理1000个单词需要大约1000倍)。总之,这是一个可扩展且高效的问题解决方案

答案 2 :(得分:0)

  1. 使用scanf
  2. 将单词读入字符串数组
  3. 对于每个单词,使用strncmp
  4. 与列表中后面的其他单词进行比较

    有速度和空间优化,但我(通常)优化以简化。

答案 3 :(得分:0)

对于更大的实现,您可以使用哈希表并检查冲突

对于小n(例如n = 10),我们可以浏览元素并将它们添加到数组中。对于每个元素,检查数组以查看它是否重复。

检查数组是否在O(n)中,并且遍历10个元素中的每一个都在O(n)中。由于我们可以使用嵌套循环简单地实现它,因此我们可以在O(n ^ 2)时间复杂度中执行此操作。这是足够的,因为如此小的n值,性能影响可以忽略不计。

答案 4 :(得分:0)

由于单个单词的长度很可能是“小”,我将以基数排序http://en.wikipedia.org/wiki/Radix_sort开始,其取O(nk)时间,其中k是最大单词长度。在这种情况下,您肯定希望首先根据长度(最多n个)将单词排序到单独的列表中。

因为您只对重复项感兴趣,所以您可以删除长度为1的任何列表(在此步骤或任何后续步骤中)。

对于每个列表,比较每个列表成员的最后一个字符,为每个看到的不同字符创建一个新的单词列表(最多26个,假设单词都是ASCII字符),截断最后一个字符。再次抛出长度为1的列表并递归地对新列表进行排序。

在最坏的情况下(所有单词长度相同,仅在第一个字符上有所不同,假设LSD基数排序),您将获得O(nk)时间。在最好的情况下(所有单词都有不同的长度),你将获得O(n)时间。在实际案例中,您可能会比O(nk)时间明显更好,因此解决方案应该可以扩展到更长的单词列表。