C++ 检测分组词的最佳方法

C++ 检测分组词的最佳方法,c++,algorithm,C++,Algorithm,对于单词中的每个字母,如果该字母的所有出现恰好形成一个连续序列,则该单词被分组。换句话说,没有两个相等的字母被一个或多个不同的字母分开 给定一个向量返回分组的字数 例如: {“ab”、“aa”、“aca”、“ba”、“bb”} 返回4 这里,“aca”不是一个组合词 我快速而肮脏的解决方案: int howMany(vector <string> words) { int ans = 0; for (int i = 0; i < words.size(); i++) {

对于单词中的每个字母,如果该字母的所有出现恰好形成一个连续序列,则该单词被分组。换句话说,没有两个相等的字母被一个或多个不同的字母分开

给定一个
向量
返回分组的字数

例如:

{“ab”、“aa”、“aca”、“ba”、“bb”}

返回4

这里,“aca”不是一个组合词

我快速而肮脏的解决方案:

int howMany(vector <string> words) {
  int ans = 0;
  for (int i = 0; i < words.size(); i++) {
       bool grouped = true;
  for (int j = 0; j < words[i].size()-1; j++)
      if (words[i][j] != words[i][j+1])
         for (int k = j+1; k < words[i].size(); k++)
           if (words[i][j] == words[i][k])
              grouped = false;
           if (grouped) ans++;
       }
   return ans;
 }
int有多少个(向量字){
int ans=0;
for(int i=0;i

我想要一个更好的算法来解决同样的问题。

这可能在每个单词的两个循环中工作:

1) 循环计算出现的不同符号的数量。(这将需要最多等于字符串长度的额外存储—可能是某种散列。)

2) 循环计算符号n与符号n+1不同的次数


如果这两个值相差不到一,则表示该单词未分组。

这可能在每个单词的两个循环中起作用:

1) 循环计算出现的不同符号的数量。(这将需要最多等于字符串长度的额外存储—可能是某种散列。)

2) 循环计算符号n与符号n+1不同的次数


如果这两个值相差不到一,则该词不会分组。

仅考虑一个词,这里有一个O(n log n)破坏性算法:

std::string::iterator unq_end = std::unique( word.begin(), word.end() );
std::sort( word.begin(), unq_end );
return std::unique( word.begin(), unq_end ) == unq_end;
Edit:第一次调用
unique
将连续字母的运行减少为单个字母。对
sort
的调用将相同的字母分组在一起。第二次调用
unique
检查
sort
是否形成了任何新的连续字母组。如果有,则该词不得分组

与其他帖子相比,它的优势在于不需要存储—尽管这不是什么优势

这里是替代algo的一个简单版本,也只需要O(1)存储(是的,也经过测试):

if(word.empty())返回true;
位集符号;
for(string::const_迭代器it=word.begin()+1;it!=word.end();+it){
如果(it[0]==it[-1])继续;
如果(符号[it[0]])返回false;
符号[it[-1]]=true;
}
回来!符号[*word.rbegin()];

请注意,要处理ASCII以外的字符,需要进行一些小的修改<代码>位集
来自标题

仅考虑一个单词,下面是一个O(n log n)破坏性算法:

std::string::iterator unq_end = std::unique( word.begin(), word.end() );
std::sort( word.begin(), unq_end );
return std::unique( word.begin(), unq_end ) == unq_end;
Edit:第一次调用
unique
将连续字母的运行减少为单个字母。对
sort
的调用将相同的字母分组在一起。第二次调用
unique
检查
sort
是否形成了任何新的连续字母组。如果有,则该词不得分组

与其他帖子相比,它的优势在于不需要存储—尽管这不是什么优势

这里是替代algo的一个简单版本,也只需要O(1)存储(是的,也经过测试):

if(word.empty())返回true;
位集符号;
for(string::const_迭代器it=word.begin()+1;it!=word.end();+it){
如果(it[0]==it[-1])继续;
如果(符号[it[0]])返回false;
符号[it[-1]]=true;
}
回来!符号[*word.rbegin()];

请注意,要处理ASCII以外的字符,需要进行一些小的修改<代码>位集来自标题

您可以使用某种类型的集(最好是插入和查找时间为O(1)的集)


每次遇到与前一个不同的字符时,请检查集合是否包含该字符。如果是这样,你的比赛就失败了。如果没有,则将其添加到集合中并继续。

您可以使用某种集合(最好是具有O(1)插入和查找时间的集合)

每次遇到与前一个不同的字符时,请检查集合是否包含该字符。如果是这样,你的比赛就失败了。如果没有,请将其添加到集合中并继续。

尝试以下操作:

bool isGrouped( string const& str )
{
  set<char> foundCharacters;
  char currentCharacter='\0';

  for( int i = 0 ; i < str.size() ; ++i )
  {
    char c = str[i];
    if( c != currentCharacter )
    {
      if( foundCharacters.insert(c).second )
      {
        currentCharacter = c;
      }
      else
      {
        return false;
      }
    }
  }
  return true;
}
bool已分组(字符串常量和字符串)
{
设置字符集;
字符currentCharacter='\0';
对于(int i=0;i
尝试以下操作:

bool isGrouped( string const& str )
{
  set<char> foundCharacters;
  char currentCharacter='\0';

  for( int i = 0 ; i < str.size() ; ++i )
  {
    char c = str[i];
    if( c != currentCharacter )
    {
      if( foundCharacters.insert(c).second )
      {
        currentCharacter = c;
      }
      else
      {
        return false;
      }
    }
  }
  return true;
}
bool已分组(字符串常量和字符串)
{
设置字符集;
字符currentCharacter='\0';
对于(int i=0;i
这里有一种方法,每个单词有两个循环,除了其中一个循环直到单词长度,但直到字母表大小。最坏的情况是O(NLs),其中N=字数,L=字长,s=字母表大小:

for each word wrd:
{
  for each character c in the alphabet:
  {
    for each letter i in wrd:
    {
      let poz = last position of character c in wrd. initially poz = -1
      if ( poz == -1 && c == wrd[i] )
         poz = i;
      else if ( c == wrd[i] && poz != i - 1 )
         // definitely not grouped, as it's separated by at least one letter from the prev sequence
    }
  }
  // grouped if the above else condition never executed
}

基本上,检查字母表中的每个字母是否不存在或仅出现在该字母的一个子串中。

这里有一种方法,每个单词有两个循环,但其中一个循环直到单词长度,但直到字母表大小。最坏的情况是O(NLs),其中N=字数,L=字长,s=字母表大小:

for each word wrd:
{
  for each character c in the alphabet:
  {
    for each letter i in wrd:
    {
      let poz = last position of character c in wrd. initially poz = -1
      if ( poz == -1 && c == wrd[i] )
         poz = i;
      else if ( c == wrd[i] && poz != i - 1 )
         // definitely not grouped, as it's separated by at least one letter from the prev sequence
    }
  }
  // grouped if the above else condition never executed
}
    public static Boolean isGrouped( String input )
    {
        char[] c = input.ToCharArray();
        int pointer = 0;
        while ( pointer < c.Length - 1 )
        {
            char current = c[pointer];
            char next = c[++ pointer];
            if (   next != current && 
                 ( next + 1 ) != current && 
                 ( next - 1 ) == current 
               ) return false; 
        }
        return true;
    }
基本上,检查是否每个