前言
哈喽大家好,我是雨墨,小老弟又来了,这是小老弟的第二篇博客,记录小老弟我刷字符串类型的leetcode 题目的笔记。每日更新3道,直至完成目标~
话不多说,咱们开始正题~~
目标已完成,本专题停止更新😁
leetcode 344 反转字符串(开胃菜)
题目链接
传送门:https://leetcode-cn.com/problems/reverse-string/
我的题解
题目描述
编写一个函数,将字符串反转过来,要求必须原地修改字符串。
样例
输入:s = ["h","e","l","l","o"]
输出:["o","l","l","e","h"]
算法
(双指针) O ( n ) O(n) O(n)
算法描述:使用两个指针,一个往后走,一个往前走,交换两个指针所指的元素,直到两个指针相遇,整个字符串就反转过来了。
class Solution {
public:
void reverseString(vector<char>& s) {
int len = s.size();
for (int head = 0, tail = len - 1; head < tail; ++head, --tail)
swap(s[head], s[tail]);
}
};
leetcode 541 反转字符串Ⅱ(换一个玩法)
题目链接
传送门:https://leetcode-cn.com/problems/reverse-string-ii/
我的题解
题目描述
给定一个字符串 s
和一个整数 k
,从字符串开头算起,每计数至 2k
个字符,就反转这 2k
字符中的前 k
个字符。
- 如果剩余字符少于
k
个,则将剩余字符全部反转。 - 如果剩余字符小于
2k
但大于或等于k
个,则反转前k
个字符,其余字符保持原样。
样例
输入:s = "abcdefg", k = 2
输出:"bacdfeg"
算法
(模拟) O ( n ) O(n) O(n)
题目要求要在每2k
个字符中选择前k
个字符反转,那每次i += 2 * k
就可以了,再多考虑数组长度满不满足大于 k 的情况就可以了。
class Solution {
public:
string reverseStr(string s, int k) {
int len = s.size();
for (int i = 0; i < len; i += 2 * k) {
int l = i, r = min(l + k, len);
reverse(s.begin() + l, s.begin() + r);
}
return s;
}
};
剑指offer 05 替换空格
题目链接
传送门:https://leetcode-cn.com/problems/ti-huan-kong-ge-lcof/submissions/
我的题解
题目描述
请实现一个函数,把字符串 s
中的每个空格替换成"%20"。
样例
输入:s = "We are happy."
输出:"We%20are%20happy."
算法1
(复制+替换) O ( n ) O(n) O(n)
将原字符串的内容拷贝到新的字符串内,如果遇到 ‘ ’, 就向新的字符串中添加%20
。但是这种空间复杂度也是 O ( n ) O(n) O(n)。
class Solution {
public:
string replaceSpace(string s) {
int len = s.size();
string str;
for (int i = 0; i < len; ++i) {
if (s[i] != ' ')
str += s[i];
else str += "%20";
}
return str;
}
};
算法2
(双指针) O ( n ) O(n) O(n)
先计算将空格替换之后新的字符串会变成多大的长度,然后对原字符串resize
这个新的长度,一个指针i
从原数组的尾部向头走,一个指针j
从新的字符串尾部向头走,如果没有遇到空格,则直接s[j--] = s[i]
,否则将空格转换成%20
。这样空间复杂度为 O ( 1 ) O(1) O(1)。
class Solution {
public:
string replaceSpace(string s) {
int len = s.size(), new_len = 0;
for (const auto& str : s) {
if (str == ' ') new_len += 3;
else new_len ++;
}
s.resize(new_len);
for (int i = len - 1, j = new_len - 1; ~i; --i) {
if (s[i] != ' ') s[j--] = s[i];
else {
s[j--] = '0';
s[j--] = '2';
s[j--] = '%';
}
}
return s;
}
};
leetcode 151 翻转字符串里的单词(好题,字符串重点题)
题目链接
传送门:https://leetcode-cn.com/problems/reverse-words-in-a-string/
我的题解
题目描述
给定一个字符串,逐个反转所有单词。
说明:
- 输入字符串
s
可以在前面、后面或者单词间包含多余的空格。 - 翻转后单词间应当仅用一个空格分隔。
- 翻转后的字符串中不应包含额外的空格。
样例
输入:s = " hello world "
输出:"world hello"
算法
(拆分问题) O ( n ) O(n) O(n)
这道题乍一看确实很难想,没办法一步到位,那就只好把这道题拆解逐个击破,这也是一种很重要的思想。
算法描述:
- 可以先将这个字符串全部反转
- 然后再逐个反转每个单题且保证每个单题之后以空格间隔,删去不必要的空格
- 更多实现细节见代码
class Solution {
public:
string reverseWords(string s) {
int len = s.size();
reverse(s.begin(), s.end()); // 先将整个字符串翻转
int beg_of_word = 0; // 每个单词的开头
for (int slowIndex = 0; slowIndex < len; ++slowIndex) {
if (s[slowIndex] == ' ') continue; // 找到第一个不是 ' ' 的字符
int fastIndex = slowIndex, end_of_word = beg_of_word;
// 寻找每一个完整的单词并用其覆盖原字符串
while (s[fastIndex] != ' ' && fastIndex < len) s[end_of_word++] = s[fastIndex++];
// 翻转每个单词
reverse(s.begin() + beg_of_word, s.begin() + end_of_word);
s[end_of_word++] = ' '; // 在每个单词末尾添加 ' '
beg_of_word = end_of_word, slowIndex = fastIndex; // 更新
}
// 只要出现一个单词,那在其末尾一定会添加一个 ' '
if (beg_of_word) --beg_of_word;
// 将末尾多余的 ' ' 删去
s.erase(s.begin() + beg_of_word, s.end());
return s;
}
};
剑指offer 58 左旋转字符串
题目链接
传送门:https://leetcode-cn.com/problems/zuo-xuan-zhuan-zi-fu-chuan-lcof/
我的题解
题目描述
字符串的左旋转操作是把字符串前面的若干个字符转移到字符串的尾部。请定义一个函数实现字符串左旋转操作的功能。比如,输入字符串"abcdefg"和数字2,该函数将返回左旋转两位得到的结果"cdefgab"。
样例
输入: s = "abcdefg", k = 2
输出: "cdefgab"
算法
(思维题) O ( n ) O(n) O(n)
这道题我是把难度调大了的,也就是在 O ( 1 ) O(1) O(1)的空间复杂度下使得字符串左旋转。遇到问题一步不能到位,那就把它拆解,先reverse
整个字符串一遍,将后 n 个字符串reverse
一遍,再将前面的字符串reverse
一遍,即可得到答案。