思路:
题目的要求:
- 限制时间为O(n)
- 将字符串大小写反转,这个遍历字符串即可,也在O(n)以内
- 反转单词的位置
方法一:双逆转 具体做法:
- 第一次反转整个字符串,这样基本的单词逆序就有了,但是每个单词的字符也是逆的
- 第二次遍历字符串的同时反转每个单词
class Solution {
public:
string trans(string s, int n) {
if(n==0)
return s;
string res;
for (int i = 0; i < n; i++)
{
if (s[i] <= 'Z' && s[i] >= 'A') //大小写转换
res += s[i] - 'A' + 'a';
else if (s[i] >= 'a' && s[i] <= 'z')
res += s[i] - 'a' + 'A';
else
res+=s[i]; //空格直接复制
}
reverse(res.begin(), res.end()); //翻转整个字符串
for (int i = 0; i < n; i++)
{
int j = i;
while(j < n && res[j] != ' ') //以空格为界,二次翻转
j++;
reverse(res.begin() + i, res.begin() + j);
i = j;
}
return res;
}
};
复杂度分析:
- 时间复杂度:O(n),虽有多个循环,但是每个循环都只有一层O(n)
- 空间复杂度:O(n),res是存储变换的临时字符串,也可以直接用s直接变换,这样就为O(1)
方法二:分割字符串+栈 因此题目要求将单词逆序, 于是可以相当按照空格把字符串分割成一个个单词,存入栈中,因此栈遵循先进后出的原理,所以可以做到单词逆序。
class Solution {
public:
string trans(string s, int n) {
if(n==0)
return s;
string res;
for (int i = 0; i < n; i++)
{
if (s[i] <= 'Z' && s[i] >= 'A') //大小写转换
res += s[i] - 'A' + 'a';
else if (s[i] >= 'a' && s[i] <= 'z')
res += s[i] - 'a' + 'A';
else
res+=s[i]; //空格直接复制
}
stack<string> temp;
for (int i = 0; i < n; i++)
{
int j = i;
while(j < n && res[j] != ' ') //以空格为界,分割单词
j++;
temp.push(res.substr(i, j - i)); //单词进栈
i = j;
}
if(s[n - 1] == ' ') //排除结尾空格的特殊情况
res = " ";
else
res = "";
while(!temp.empty()){ //栈遵循先进后厨,单词顺序是反的
res += temp.top();
temp.pop();
if(!temp.empty())
res += " ";
}
return res;
}
};
复杂度分析:
-
时间复杂度:O(n),所有循环最多遍历一次
-
空间复杂度:O(n),栈空间