我当前正在做一个leetcode问题,我必须在一个句子中找到一个前缀并返回该句子中的单词编号,否则返回-1。我想出了一个解决方案,但是它崩溃了一些字符串,我不知道为什么。以下是一个示例:
输入:句子=“我喜欢吃汉堡”,搜索字词=“汉堡”
输出:4(我也得到4的输出)
说明:“ burg”是句子中第4个单词“ burger”的前缀。
但此示例失败:
输入:句子=“这个问题很容易解决”,searchWord =“ pro”
输出:2(我得到6的输出)
说明:“ pro”是“ problem”的前缀,problem是句子中的第二个和第六个词,但是我们返回2,因为它是最小索引。
我为此的cout
产生了一个非常奇怪的代码段:
problem is an easy problem
problem is an easy problem
problem is an easy problem
problem is an easy problem
probl
proble
problem
problem
problem i
problem is
当我增加时,它完全忽略了前几个子字符串,这是它唯一发生的时间。
int isPrefixOfWord(string sentence, string searchWord)
{
string sub;
int count = 1;
for (int i = 0; i < sentence.length(); i++)
{
if (sentence[i] == ' ')
count++;
for (int j = i; j < sentence.length(); j++)
{
sub = sentence.substr(i, j);
cout<<sub<<endl;
if (sub == searchWord)
{
return count;
}
}
}
return -1;
}
有什么想法吗?
int isPrefixOfWord(string sentence, string searchWord)
{
string sub;
int count = 1;
for (int i = 0; i < sentence.length() - searchWord.length() - 1; i++)
{
if (sentence[i] == ' ')
count++;
sub = sentence.substr(i,searchWord.length());
if ( sub == searchWord && (sentence[i-1] == ' ' || i == 0))
{
return count;
}
}
return -1;
}
答案 0 :(得分:2)
影响函数输出的错误是您没有在内部for循环中处理i
的增量:
for (int i = 0; i < sentence.length(); i++)
{
if (sentence[i] == ' ')
count++;
for (int j = i; j < sentence.length(); j++)
{
sub = sentence.substr(i, j);
cout<<sub<<endl;
if (sub == searchWord)
{
return count;
}
}
}
请注意,一旦您的内循环完成,i
总是会迭代一个。因此,您对单词的下一次搜索将错误地从其下一个字符开始,错误地搜索了“子单词”而不是前缀,因此会产生误报(和不必要的工作)。
还请注意,每次您这样做:
(sub == searchWord)
即使我们只对第j
个新字符是否匹配感兴趣,这也会检查所有j
个字符。
另一个错误,它会影响您的性能和cout
,这是因为您没有处理不匹配的情况:
if (sub == searchWord)
...从不虚假,因此退出内部循环的唯一方法是保持增量j
到数组末尾,因此sub
最终变得很大。
解决第二个错误的一种方法是像这样替换内部循环:
if (sentence.substr(i, i + searchWord.length()) == searchWord)
return count;
最后,修复所有错误:
int isPrefixOfWord (const string & sentence, const string & searchWord)
{
if (sentence.length() < searchWord.length())
return -1;
const size_t i_max = sentence.length() - searchWord.length();
for (size_t i = 0, count = 1; ; ++count)
{
// flush spaces:
while (sentence[i] == ' ')
{
if (i >= i_max)
return -1;
++i;
}
if (sentence.substr(i, searchWord.length()) == searchWord)
return count;
// flush word:
while (sentence[i] != ' ')
{
if (i >= i_max)
return -1;
++i;
}
}
return -1;
}
请注意,substr
提供了对象的副本(不仅仅是字符串的包装器),因此相对于searchWord.length()
,这花费了线性时间,这在{{ 1}}较小。
我们可以通过替换来提高速度
sentence
...与
if (sentence.substr(i, searchWord.length()) == searchWord)
return count;
其他人已经展示了可以解决问题的库的不错的应用程序。
如果您无权访问这些库进行分配,或者仅想学习如何在不降低效率的情况下模块化这样的问题,那么可以通过以下方法在 for (size_t j = 0; sentence[i] == searchWord[j]; )
{
++j;
if (j == searchWord.size())
return count;
++i;
}
中进行操作:任何库(c++11
除外):
string
关于速度:如果我们认为bool IsSpace (char c)
{
return c == ' ';
}
bool NotSpace (char c)
{
return c != ' ';
}
class PrefixFind
{
using CharChecker = bool (*)(char);
template <CharChecker Condition>
void FlushWhile ()
{
while ((m_index < sentence.size())
&& Condition(sentence[m_index]))
++m_index;
}
void FlushWhiteSpaces ()
{
FlushWhile<IsSpace>();
}
void FlushToNextWord ()
{
FlushWhile<NotSpace>();
FlushWhile<IsSpace>();
}
bool PrefixMatch ()
{
// SearchOngoing() must equal `true`
size_t j = 0;
while (sentence[m_index] == search_prefix[j])
{
++j;
if (j == search_prefix.size())
return true;
++m_index;
}
return false;
}
bool SearchOngoing () const
{
return m_index + search_prefix.size() <= sentence.size();
}
const std::string & sentence;
const std::string & search_prefix;
size_t m_index;
public:
PrefixFind (const std::string & s, const std::string & sw)
: sentence(s),
search_prefix(sw)
{}
int FirstMatchingWord ()
{
const int NO_MATCHES = -1;
if (!search_prefix.length())
return NO_MATCHES;
m_index = 0;
FlushWhiteSpaces();
for (int n = 1; SearchOngoing(); ++n)
{
if (PrefixMatch())
return n;
FlushToNextWord();
}
return NO_MATCHES;
}
};
的长度为sentence
,而m
的长度为searchWord
,则原始(越野车)代码具有n
的时间复杂度。但是有了这项改进,我们得到了O(n*m^2)
。
答案 1 :(得分:2)
使用starts_with的非常简单的C++20
解决方案:
#include <string>
#include <sstream>
#include <iostream>
int isPrefixOfWord(std::string sentence, std::string searchWord)
{
int count = 1;
std::istringstream strm(sentence);
std::string word;
while (strm >> word)
{
if ( word.starts_with(searchWord) )
return count;
++count;
}
return -1;
}
int main()
{
std::cout << isPrefixOfWord("i love eating burger", "burg") << "\n";
std::cout << isPrefixOfWord("this problem is an easy problem", "pro") << "\n";
std::cout << isPrefixOfWord("this problem is an easy problem", "lo");
}
输出:
4
2
-1
当前,LeetCode和许多其他在线编码站点不支持C ++ 20,因此此代码将无法在那些在线平台上成功编译。
答案 2 :(得分:0)
我们只能使用std::basic_stringstream
解决此问题。这将通过:
beforeEach(() => {
TestBed.configureTestingModule({
imports: [TestModuleForAll],
providers: []
});
});