如果对于单词中的每个字母,该字母的所有出现恰好形成一个连续序列,则对单词进行分组。换句话说,没有两个相等的字母被一个或多个不同的字母分开。
给定vector<string>
返回分组字数。
例如:
{“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;
}
我想为同样的问题找到更好的算法。
答案 0 :(得分:2)
尝试以下方法:
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;
}
答案 1 :(得分: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;
编辑:对unique
的第一次调用会减少连续字母到单个字母的运行。对sort
的调用将相同的字母组合在一起。第二次调用unique
会检查sort
是否形成任何新的连续字母组。如果确实如此,则不得对该单词进行分组。
与其他人发布的优势在于它不需要存储 - 尽管这不是一个优势。
这是替代算法的简单版本,也只需要O(1)存储(是的,也经过测试):
if ( word.empty() ) return true;
bitset<CHAR_MAX+1> symbols;
for ( string::const_iterator it = word.begin() + 1; it != word.end(); ++ it ) {
if ( it[0] == it[-1] ) continue;
if ( symbols[ it[0] ] ) return false;
symbols[ it[-1] ] = true;
}
return ! symbols[ * word.rbegin() ];
请注意,您需要进行少量修改才能使用ASCII以外的字符。 bitset
来自标题<bitset>
。
答案 2 :(得分:1)
您可以使用某种类型的集合(最好使用O(1)插入和查找时间)。
每次遇到与前一个字符不同的字符时,请检查该字符集是否包含该字符。如果是,则您的匹配失败。如果没有,请将其添加到集合中并继续。
答案 3 :(得分:0)
这可能在每个单词的两个循环中起作用:
1)循环计算出现的不同符号的数量。 (这将需要额外的存储空间,最多等于字符串的长度 - 可能是某种哈希值。)
2)循环计算符号n与符号n + 1不同的次数。
如果这两个值之间没有恰好相同,则该单词不会被分组。
答案 4 :(得分:0)
这是一种每个单词有两个循环的方法,除了其中一个循环直到单词长度,但直到字母大小。最坏的情况是O(N L s),其中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
}
基本上,检查字母表中的每个字母是否都不存在,或者只出现在那些字母的一个子字符串中。
答案 5 :(得分:0)
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;
}
(C#但校长适用)
答案 6 :(得分:0)
这是一个多行,详细,正则表达式来匹配失败:
(?: # Non capturing group of ... (\S)\1* # One or more of any non space character (capured). ) (?! # Then a position without \1 # ... the captured character ).+ # ... at least once. \1 # Followed by the captured character.
或更小:
"(?:(\S)\1*)(?!\1).+\1"
我只是假设C ++有一个regexp实现,它可以在Python中运行,也可以在Perl和Ruby中运行。