题目目录
● 344.反转字符串
● 541. 反转字符串II
● 剑指Offer 05.替换空格
● 151.翻转字符串里的单词
● 剑指Offer58-II.左旋转字符串
344.反转字符串
344.反转字符串
很经典的字符串考察点,考察对双指针的熟悉程度。
解法是通过双指针从字符串数组两边向中间靠拢,交换字符。
void reverseString(vector<char>& s)
{
int left = 0;
int right = s.size() - 1;
while (left < right) {
char tmp = s[left];
s[left] = s[right];
s[right] = tmp;
left++;
right--;
}
}
541. 反转字符串II
541. 反转字符串II
解题的思路比上一题复杂一点,但是思路还是一样的,不同之处在于外层多了循环。
string reverseStringII(string s, int k)
{
int strLen = s.size();
int leftLen = strLen;
while (leftLen > 0) {
int left = strLen - leftLen;
int right = left + k -1;
if (leftLen < k) {
right = strLen - 1;
}
while (left < right) {
char tmp = s[left];
s[left] = s[right];
s[right] = tmp;
left++;
right--;
}
leftLen = leftLen - 2 * k;
}
return s;
}
剑指Offer 05.替换空格
剑指Offer 05.替换空格
主要思路是先统计空格个数,对数组扩容,利用双指针从数组尾部往前填充
string replaceBlackChar(string s)
{
// 获取空格个数
int spaceCount = 0;
for (int i = 0; i < s.size(); ++i) {
if (s[i] == ' ')
spaceCount++;
}
int strLen = s.size();
// 扩容
s.resize(strLen + spaceCount * 2);
// 双指针移动
int left = strLen - 1;
int right = s.size() - 1;
while (left >= 0) {
if (s[left] == ' ')
{
s[right--] = '0';
s[right--] = '2';
s[right--] = '%';
} else {
s[right--] = s[left];
}
left--;
}
return s;
}
151.翻转字符串里的单词
151.翻转字符串里的单词
思路是找到空格,分割单词,然后填充到str
O(n + n) 空间 O(n)
string reverseWord(string str)
{
vector<string> vec;
int index = 0;
int ret = 0;
while ((ret = str.find(' ', index)) != str.npos) {
vec.push_back(str.substr(index, ret - index));
index = ret + 1;
}
index = str.size() - 1;
for (auto val : vec) {
for (auto i = val.size() - 1; i >= 0; --i) {
str[index--] = val[i];
}
if (index > 0)
str[index--] = ' ';
}
return str;
}
上面的解法使用到了O(n)的额外空间及substr字符串函数,尽量别使用库函数来实现。
下面是高效解法:
// 思路:
// 删除多余空格
// 从后往前移动,覆盖掉多余空格
// 就是数组元素删除操作
string removeExtraSpace(string s)
{
int slow = 0;
for (int i = 0; i < s.size(); ++i) {
if (s[i] != ' ') {
if (slow != 0) s[slow++] = ' ';
while (i < s.size() && s[i] != ' ') {
s[slow++] = s[i++];
}
}
}
s.resize(slow);
return s;
}
//
string reverseWord2(string s)
{
// 去除多余空格
s = removeExtraSpace(s);
// 反转
int left = 0;
int right = s.size() - 1;
while (left < right) {
char ch = s[left];
s[left++] = s[right];
s[right--] = ch;
}
// 单词反转
left = 0;
while (left < s.size()) {
right = left + 1;
while (right < s.size() && s[right] != ' ')
right++;
int tmp = right;
right -= 1;
while (left < right) {
char ch = s[left];
s[left++] = s[right];
s[right--] = ch;
}
left = tmp + 1;
}
return s;
}
剑指Offer58-II.左旋转字符串
剑指Offer58-II.左旋转字符串
//
string leftReverseString(string s, int n)
{
// 整体反转
int left = 0;
int right = s.size() - 1;
while (left < right) {
char ch = s[left];
s[left++] = s[right];
s[right--] = ch;
}
// 最后n个字符反转
left = s.size() - n;
right = s.size() - 1;
while (left < right) {
char ch = s[left];
s[left++] = s[right];
s[right--] = ch;
}
// 剩下字符反转
left = 0;
right = s.size() - n - 1;
while (left < right) {
char ch = s[left];
s[left++] = s[right];
s[right--] = ch;
}
return s;
}