2021年2月7日日曜日、天気は良いです[過去を嘆いたり、現在を無駄にしたり、未来を恐れたりしないでください]
この記事の内容
1.はじめに
2.解決策
2.1新しい配列を開き、ダブルポインタを使用して後ろから前に繰り返します
このメソッドのアイデアは比較的単純で、コードは実装が簡単です。欠点は、新しい配列を開く必要があり、スペースの複雑さがO(n)であるということです。
class Solution {
public:
string reverseWords(string s) {
int j = s.size() - 1, i = 0;
string res;
// 从后往前获取每个单词,在这个过程中,首尾的空格也被忽略掉了
while(i>=0 && j>=0){
while(j>=0 && s[j]==' ') --j;
i = j;
while(i>=0 && s[i]!=' ') --i;
// 得到一个单词的首尾索引,添加到新建的字符串中
res.append(s.substr(i+1, j-i));
res.append(1,' ');
j = i;
}
// 最后的结果尾部可能会有1个或2个空格,删除之
j = res.size()-1;
while(j>=0 && res[j]==' ') --j;
return res.substr(0,j+1);
}
};
2.2 O(1)の空間の複雑さを伴う解法:最初に全体的な反転、次に部分的な反転
最初に文字列の最初と最後のスペースを削除し、次に全体を裏返し、最後に各単語を部分的に裏返して最終結果を取得します。この方法は実装が少し複雑ですが、スペースの複雑さはO(1)だけです。
class Solution {
public:
string reverseWords(string s) {
if(s.empty()) return s;
// 删除字符串首尾的空格
trim(s);
int n = s.size();
// 整体翻转字符串
reverse(s, 0, n-1);
int i = 0, j = 0;
while(i<n && j<n){
// 找到一个单词的首尾,进行局部翻转
while(j<n && s[j] != ' ') ++j;
reverse(s, i, j-1);
i = j;
// 让i指向下一个单词的首部
while(i<n && s[i] == ' ') ++i;
// 删除两个单词之间的空格
s.erase(j,i-j-1);
// 注意!!! !!!!!!
// 删除空格之后,字符串的长度可能发生了变化,因此i、j、n的值都要进行更新
i = j + 1;
j = i;
n = s.size();
}
return s;
}
// 删除字符串首尾的空格
void trim(string& ss){
if (ss.empty()) return;
int i = 0;
while (i < ss.size() && ss[i] == ' ') ++i;
ss.erase(0, i);
int j = ss.size() - 1;
while (j >= 0 && ss[j] == ' ') --j;
ss.erase(j+1);
}
// 翻转字符串
void reverse(string& ss, int beg, int end){
if(beg<0 || beg>=ss.size() || end<0 || end>=ss.size()) return;
while(beg<end){
char tmp = ss[beg];
ss[beg] = ss[end];
ss[end] = tmp;
++beg;
--end;
}
}
};
参照
「ソードフィンガーオファー第2版」
https://leetcode-cn.com/problems/fan-zhuan-dan-ci-shun-xu-lcof/solution/zi-jie-ti-ku-jian-58-i-jian-dan-fan-zhua- qwyg /