降低o(n ^ 3)c ++代码的复杂性

Pat*_*tes 5 c++ algorithm performance for-loop code-complexity

我想降低以下算法的复杂性.基本上,它需要一个单词作为输入并计算其中的唯一字母数(单词的"熵").我目前的解决方案采用3个嵌入式for循环,其复杂度为o(n ^ 3).由于此代码是更大项目的一部分(我们为游戏构建了一个称为boggle的解算器),我希望降低算法的复杂性,以减少其执行时间.提前致谢!

int wordEntropy(string word)
{

int length = word.length();
int uniquewords = length;
string compare = word;
char save[17];
int cond=0;

for (int ii=0; ii < length; ii++)
{

    for (int jj=ii+1; jj < length; jj++)
    {
        for (int kk=0; kk<= ii; kk++)
        {
            if (save[kk] == word[ii]) {cond++;}
        }
        if (word[ii] == word[jj])
        {
            if (cond>0) {break;}
            uniquewords--;
        }
    }

    save[ii] = word[ii];
    cond = 0;

}
return uniquewords;
}
Run Code Online (Sandbox Code Playgroud)

nne*_*neo 13

一个便宜的解决方案就是将字符粘贴在一个unordered_set,这是一个哈希集(分摊O(1)插入和查找):

#include <unordered_set>

int wordEntropy(const std::string &word) {
    std::unordered_set<char> uniquechars(word.begin(), word.end());
    return uniquechars.size();
}
Run Code Online (Sandbox Code Playgroud)

这产生了O(n)的复杂性,这与它得到的一样好.


Pet*_*ker 10

在没有任何额外(和耗时)内存分配的情况下进行计算:

std::sort(word.begin(), word.end());
auto last = std::unique(word.begin(), word.end());
return last - word.begin();
Run Code Online (Sandbox Code Playgroud)

  • @nneonneo - 对于典型的Boggle字样,差异(与使用某种形式的集合相比)很重要:集合的所有内存开销和运行时复杂性远远超过排序短字所需的"额外"工作.绩效评估远不如渐近复杂性. (3认同)

Mar*_*ayr 9

如果这真的是关于性能,取决于有效字符的范围,这样的事情可能会更快:

std::size_t wordEntropy( const std::string & word )
{
    unsigned char seen[256] = { 0 };
    for( unsigned char c : word )
    {
        ++seen[ c ];
    }
    return std::count_if( & seen[0], & seen[ 0 ] + 256,
                          []( unsigned char c ) { return c != 0; } );
}
Run Code Online (Sandbox Code Playgroud)

但显然,这有点难以维护.该解决方案保证了O(n)的复杂性,并且它不会进行任何动态内存分配.

如果字符出现次数超过255次,则没有问题的替代版本:

std::size_t wordEntropy( const std::string & word )
{
    bool seen[256] = { false };
    for( unsigned char c : word )
    {
        seen[ c ] = true;
    }
    return std::count_if( & seen[0], & seen[ 0 ] + 256,
                          []( bool t ) { return t; } );
}
Run Code Online (Sandbox Code Playgroud)

  • 你还需要用`std :: numeric :: limits <std :: string :: value_type> :: max()`替换'256`,以防你遇到16位字符. (2认同)