版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_28584889/article/details/83787533
问题如下
刚看这道题目以为很简单,直接调用C++的rfind()函数,以为几行代码就可以搞定,结果发现,测试用例太刁钻了,各种测试用例想不到的情况。比如以下这些测试用例:
" ab "
"a"
"a "
""
" "
" "
没办法,只能采用最有效的方法——遍历字符串,将所有单词全部分离出来,代码如下:
//方法一:遍历字符串,分离出所有单词
int lengthOfLastWord(string s) {
if(s.empty())
return 0; //如果字符串为空,直接返回0
vector<string> word; //将s中的单词一个一个拆出来放到容器word中
int begin, lenWord = 0; //begin用于记录一个单词首字母的位置,lenWord记录单词的长度
for (int i = 0; i < s.size(); i++)
{
if((i == 0 && s[i] != ' ') || (i != 0 && s[i - 1] == ' ' && s[i] != ' '))
{ //一个单词首字母的开始有两种情况:1、字符串开始位置就是一个字母;2、一个单词前面是一个空格
begin = i;
lenWord++;
if(i == s.size() - 1) //字符串中只有一个字符
{
word.push_back(s.substr(begin, lenWord));
break;
}
}else if(s[i] != ' ' && i != s.size() - 1){ //如果不是前面的情况,而且该字符又不是空格,那它必然是某个单词的字符,注意考虑是不是字符串最后一个位置
lenWord++;
}else if(i != 0 && s[i - 1] != ' ' && s[i] == ' '){ //如果当前字符为空格,而且上一个不为空格,那么意味着一个单词已经拆分出来了,i!=0是为了防止下标越界
word.push_back(s.substr(begin, lenWord));
lenWord = 0;
}else if(s[i] != ' ' && i == s.size() -1){ //拆分某个单词的时候,字符串突然结束的情况
word.push_back(s.substr(begin, lenWord + 1));
}
}
//打印出所有单词
/*cout << "word:" << endl;
for (int j = 0; j < word.size(); j++)
{
cout << word[j] << endl;
}
cout << endl;*/
if(word.empty()) //如果word为空,说明没有单词拆出来
return 0;
else //如果不为空,返回最后一个元素的长度
return word[word.size() - 1].size();
}
上面的算法虽然是线性时间复杂度,但是使用了数组空间,我们可以在遍历字符串的时候只记录最后一个单词的长度就好;基本思路是:如果当前遍历的字符不是空格就计数值加一,如果当前遍历的字符为空格同时下一个字符不是空格就计数值清零。代码如下:
//方法二:遍历字符串,将最后一个单词的长度计算出来就好
int lengthOfLastWord(string s) {
int countWord = 0; //用于记录单词的长度
for (int index = 0; index < s.size(); index++)
{
if(s[index] == ' ')
{
if(index != s.size() - 1 && s[index + 1] != ' ')
{ // 当前为空格,下一个不是空格,那么countWord需要清零,重新计算
countWord = 0;
continue;
}
else
continue;
}
countWord++; //当前不是空格就加一
}
return countWord;
}