1. 程式人生 > >LeetCode58.最後一個單詞的長度(C++實現)

LeetCode58.最後一個單詞的長度(C++實現)

問題如下

剛看這道題目以為很簡單,直接呼叫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;
}