在查找数据结构的顺序时感到困惑

时间:2010-02-27 06:48:15

标签: algorithm data-structures trie

今天我参加了一家公司的笔试。整体测试侧重于数据结构。我遇到了一个我认为已经解决的问题。但我在计算数据结构的Big O函数时遇到了困难。我将提出我提出的问题和答案。

  

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

     
      
  1. 您将选择哪种数据结构
  2.   
  3. 提供算法
  4.   
  5. 算法的顺序是什么
  6.   

对于问题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)。

提示/提示/建议是开放的!

修改:更正了问题,明确提到应为所有唯一字词存储字数。

2 个答案:

答案 0 :(得分:2)

比较两个通用字符串取Θ(k)(k = min strlen),并且字数是N,你必须查看,所以Ω(Nk)应该是你能得到的最有效的复杂性。

答案 1 :(得分:1)

如果你真的想使用特里,那么addToTrie()确实会 O(k),其中k是你要添加的单词的长度。 constructTrie()将采用 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;

这将为您提供构建特里结构的 O(C)运行时间,其中<​​strong> C 是文档中的字符数。

现在,这引出了一个问题:为什么你需要特里?显然你想出了一种方法来检测一个单词何时结束,那么为什么必须将你的单词添加到一个单词?这太过分了。您需要的唯一数据结构是一些变量:一个用于跟踪当前字符,一个用于跟踪前一个字符,另一个用于计算单词。这很容易在 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来解决这个问题是没有意义的,这只会使事情复杂化。我想如果他们想测试你对尝试的了解,那么他们就会给你一个问题,让你更有意义。

即使他们给你一个getNextWord()功能(你有没有使用它?因为没有它你可以做得更好),我猜它会在没有更多单词的情况下返回“\ 0”或其他东西?那么为什么你不能直接调用它直到它返回“\ 0”并计算这样的单词?无论哪种方式,特里在这里都没有意义。