【问题标题】:count co-ocurrence sorted vector string c++计数共现排序向量字符串c ++
【发布时间】:2013-07-25 21:32:19
【问题描述】:

我有一个排序的字符串向量,我试图找到向量中每个元素的共现:

V = {"AAA","AAA","AAA","BCA",...}

int main()
{
      vector<string> vec;
      //for every word in the vector
      for(size_t i = 0; i < vec.size();i++)
       {

             int counter = 0;
              //loop through the vector and count the coocurrence of this word
             for(size_t j = 0; j < vec.size();j++)
              {
                 if(vec[i] == vec[j]) counter +=1;
              }

              cout << vec[i] << "    "<<counter <<ed,l
         }
}

复杂度是 O(n^2) 对吧?太费时间了,怎么解决呢?

谢谢,

这就是编辑:

int main()
{
      vector<string> vec;
      //for every word in the vector
      for(size_t i = 0; i < vec.size();i++)
       {

             int counter = 0;
              //loop through the vector and count the coocurrence of this word
             for(size_t j = i+1; j < vec.size()-1;j++)
              {
                 if(vec[i] == vec[j]) counter +=1;
              }

              cout << vec[i] << "    "<<counter <<ed,l
         }
}

【问题讨论】:

  • 已经排序了吗?
  • @hivert 是的,向量已经排序了
  • 即使它没有排序,将它的运行时间减半也是微不足道的。 for(size_t j=i+1; ...)
  • @MooingDuck:但是还是 O(n*n)
  • 是的,它将是 O(n^2)

标签: c++ string algorithm sorting vector


【解决方案1】:

未测试。我假设向量至少包含一个元素。

counter = 1
for(size_t i = 1; i < vec.size(); i++)
  {
    if(vec[i] == vec[i-1]) counter +=1;
    else 
      {
         std::cout << vec[i-1] << ", " << counter << std::endl;
         counter = 1;
      }
  }
std::cout << vec[i-1] << ", " << counter << std::endl;

这显然是 O(n)。与您的代码略有不同:每个单词只打印一次。

【讨论】:

  • 因此,对于每个单词,只要它相同,我都会在计数器上加 +1,直到它不同为止。
  • so close。哦,你编辑了关于零元素案例的评论:P
  • @Mooing Duck。在文章开头阅读我的假设。
  • 确实发生了变化。我希望在明天中午之前完成计数。我知道这不是测量时间的正确方法,而只是一个近似值:Run1: 5.081, Run2: 6.053, Run3: 5.068
  • @hivert:这至少是 O(N*|S|),大约是 O(N^2)。比较 2 个字符串需要 O(|S|) 运行时间,其中 |S|=length of string S
【解决方案2】:

经过测试,O(n),即使向量未排序或为空也有效:

#include <iostream>
#include <vector>
#include <unordered_map>

int main()
{
    std::vector<std::string> v = { "aaa", "abc", "aaa", "def", "aaa", "aaa", "abc", "ghi" };
    std::unordered_map<std::string, int> m;

    for (std::vector<std::string>::iterator it = v.begin(); it != v.end(); it++)
        m[*it]++;

    for (std::unordered_map<std::string, int>::iterator it = m.begin(); it != m.end(); it++)
        std::cout << it->first << " -> " << it->second << std::endl;

    return 0;
}

或者,为了可读性,使用基于范围的循环重新编写了适当的 sn-p(感谢 Frerich Raabe):

for (const auto it: v)
    m[it]++;

for (const auto it: m)
    std::cout << it.first << " -> " << it.second << std::endl;

【讨论】:

  • 但是,它的内存是 O(n),而我的解决方案是 O(1)。
  • @hivert 但是,要求是更严格的运行时间,而不是更低的内存使用量。
  • 如果你使用std::unordered_map和初始化列表,你也可以使用基于范围的for循环和auto来大大缩短你的代码,例如for ( const auto &amp;s: v ) m[s]++;.
  • @H2CO3 请不要太酸 ;-) 我仍然敢打赌我的代码比你的更快...
  • 我会尝试两者都非常有趣。我有一个大小为 106207 的向量。非常感谢
猜你喜欢
  • 2011-10-30
  • 2016-03-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多