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

时间:2016-10-31 14:27:39

标签: 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;
}

4 个答案:

答案 0 :(得分: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();
}

这会产生O(n)的复杂性,这与它的效果一样好。

答案 1 :(得分:10)

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

import javax.persistence.*;

@Entity
@Table(name = "EMPLOYEE")
public class Employee {
   @Id @GeneratedValue
   @Column(name = "id")
   private int id;

   @Column(name = "first_name")
   private String firstName;

   @Column(name = "last_name")
   private String lastName;

   @Column(name = "salary")
   private int salary;  

   public Employee() {}
   public int getId() {
      return id;
   }
   public void setId( int id ) {
      this.id = id;
   }
   public String getFirstName() {
      return firstName;
   }
   public void setFirstName( String first_name ) {
      this.firstName = first_name;
   }
   public String getLastName() {
      return lastName;
   }
   public void setLastName( String last_name ) {
      this.lastName = last_name;
   }
   public int getSalary() {
      return salary;
   }
   public void setSalary( int salary ) {
      this.salary = salary;
   }
}

答案 2 :(得分: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; } );
}

但显然,这有点难以维持。该解决方案具有保证的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; } );
}

答案 3 :(得分:0)

如果字符串很短,那么你应该比big-O更担心内存分配。无论哪种方式,这都是一个更快的解决方案。

既然你提到这是一个boggle游戏,并且这个函数的输入是一个名为&#34; word&#34;的字符串,我假设你已经验证了&#34;中的所有字符。字&#34;是ascii字母字符。如果是这样,这里可能是最快的情况不变的熵计数:

int word_entropy ( std::string const& word )
{
    uint32_t bit_map = 0;
    for ( char const ch : word )
        bit_map |= static_cast <uint32_t> ( 1 ) << ( ch & 31 );
    return __builtin_popcount ( bit_map );
}