Algorithm 查找数据结构顺序时的混乱

Algorithm 查找数据结构顺序时的混乱,algorithm,data-structures,trie,Algorithm,Data Structures,Trie,今天我参加了一家公司的笔试。整个测试集中在数据结构上。我有个问题,我想我已经解决了。但是我在计算数据结构的大O函数时遇到了困难。我将提供我提出的问题和答案 给定您需要存储的文档和文档中的单词,并应能够在输入任何单词时返回计数。系统为您提供了char*GetNextWord() 您将选择什么数据结构 给出了算法 你的算法的顺序是什么 对于问题1,我写了我将选择TRIE数据结构。对于问题2,我给出了一个简单的算法。我写道,我将构建TRIE数据结构,如下所示 struct TRIE{ boolean

今天我参加了一家公司的笔试。整个测试集中在数据结构上。我有个问题,我想我已经解决了。但是我在计算数据结构的大O函数时遇到了困难。我将提供我提出的问题和答案

给定您需要存储的文档和文档中的单词,并应能够在输入任何单词时返回计数。系统为您提供了
char*GetNextWord()

  • 您将选择什么数据结构
  • 给出了算法
  • 你的算法的顺序是什么
  • 对于问题1,我写了我将选择TRIE数据结构。对于问题2,我给出了一个简单的算法。我写道,我将构建TRIE数据结构,如下所示

    struct TRIE{
     boolean isWord;
     int count;
     Node* myList;
    }
    
    struct Node{
     char* character;
     Node *next;
     TRIE *child;
    }
    
    我有方法
    constructTrie()
    ,它将对每个单词执行
    addToTrie()

    我写了
    addToTrie()
    的顺序是O(k),其中k是长度。
    constructTrie()
    的顺序是N*O(k),其中N是字数

    现在我的问题是: 我提到的命令是否正确?如果没有,未来如何解决此类问题(给定ds查找顺序)。使用O(k)后我真的很困惑。它使我假设O(1)

    提示/提示/建议是完全开放的


    编辑:更正了问题,明确提到应为所有唯一的单词存储单词计数。

    比较两个通用字符串时,取Θ(k)(k=min strlen),您必须查看的单词数为N,因此Ω(Nk)应该是你能得到的最有效的复杂度。

    如果你真的想使用trie,那么
    addToTrie()
    实际上应该是O(k)其中k是你要添加的单词的长度
    constructrie()
    将取O(Nk)其中N是字数,如果您只需为每个单词调用
    addToTrie()
    。但是,您不需要为每个单词调用
    addToTrie()
    函数。添加完单词后,只需将trie指针重置为trie的根,然后在移动当前单词时移动指针,同时添加字符。伪代码:

    trieNode *curr = trieRoot;
    for each character c in document
      if it's a word terminator (space etc)
        add a character at curr signaling the end of the current word ('\0' maybe);
        curr = trieRoot;
      else if character is not a separator
        add character c at curr->next->character[c];
        curr = curr->next;
    
    这将为您提供构建trie的O(C)运行时间,其中C是文档中的字符数

    现在,这就引出了一个问题:为什么您需要trie?显然,您找到了一种检测单词何时结束的方法,那么为什么必须将单词添加到trie中呢?这太过分了。唯一需要的数据结构是几个变量:一个用于跟踪当前字符,一个用于跟踪前一个字符,一个用于计算单词数。这在O(C)中很容易做到,如下所示:

    char prev = '\0';
    char curr;
    int count = 0;
    
    for each character curr
      if curr is a word separator and prev isn't 
        ++count;
      prev = curr;
    
    我认为对这个问题使用trie是没有意义的,它只会使事情复杂化。我认为,如果他们想测试你的尝试知识,他们会给你一个问题,其中trie更有意义


    即使他们给了你一个
    getNextWord()
    函数(你必须使用它吗?因为没有它你可以做得更好),我猜它会在没有更多单词的情况下返回“\0”或其他什么?那么,为什么不能直接调用它,直到它返回“\0”,然后像这样计算单词数呢?不管怎样,trie在这里都没有意义。

    你的
    trie
    结构中缺少一个重要成员吗?@Kenny:是的,很抱歉它应该有一个字符。要么你把我的问题搞错了,要么我没有解释。这不仅仅是计算字数。这是计算独特的单词。在构建数据结构之后,我应该能够给出输入的任何单词的字数,我强烈支持在这里使用TRIE的想法。如果我的问题含糊不清,我道歉。让我纠正一下对不起,我以为你只需要数一数单词。在这种情况下,忽略我文章的第二部分。trie是个不错的选择。不过我的第一部分仍然有效——您可以在O(C)中构建您的trie(假设您不必使用getNextWord()函数,如果您这样做的话,您的解决方案是好的)并回答O(k)中长度为k的单词的任何查询。感谢您的理解。根据你的解,我们可以在O(C)时间内找到它,但这等于O(Nk),对吗?我必须使用getNextWord()的原因是,它是我唯一可用的公共方法。我没有指向文档的指针。也许,我下次发帖时应该更清楚:)O(C)和O(Nk)在理论上是一样的,但在实践中我的O(C)解决方案会更快。如果有一个过程将getNextWord()检索到的单词插入到trie中,那么首先getNextWord()必须获取单词,即O(k),然后插入过程将需要O(k)将其插入到trie中。所以基本上你将遍历每个单词,每个字符,两次,而我的解决方案只检查每个字符一次。无论如何,如果必须使用getNextWord(),则我所说的不适用,因此算法的运行时间是O(Nk)或O(C)。在问题陈述的给定约束下,您的解决方案在理论和实践上都是最优的。O(Nk)==O(C),因为Nk基本上是C(N个单词,k个平均单词长度,将它们相乘,得到一个平均字符数,意思是C)。我用O(C)来强调这样一个事实,即算法是不同的,总体上更好一些。