344.反转字符串
补充知识:
- swap函数
- 用于交换两个变量的值
- 实现原理:
- ^=
- 如果两个位相同,则结果为0;如果两个位不同,则结果为1
思路: 双指针
class Solution {
public:
void reverseString(vector<char>& s) {
int l = 0, r = s.size() - 1;
while (l <= r) {
char tem = s[r];
s[r--] = s[l];
s[l++] = tem;
}
}
};
541. 反转字符串II
补充知识:
1.reverse函数的使用(操作区间是左闭右开)
//nums.begin() + 1 = 2
//nums.begin() + 5 = 6
//操作区间为左闭右开
//1 [2 3 4 5] 6 7 8 9 实际操作区间
//1 [5 4 3 2] 6 7 8 9 结果
std::reverse(nums.begin() + 1, nums.begin() + 5);
状态:
需要重新回看, 实现存在问题
弄清楚遍历的顺序, i , i + k 和 i + 2k 是关键点
思路: 模拟实现的过程, 不涉及具体的算法
卡码网:54.替换数字
补充知识:
- resize函数
std::vector<int> vec;
vec.push_back(10);
vec.push_back(20);
vec.resize(5); //将vec的大小调整为5,[10, 20, 0, 0, 0]
vec.resize(6, 1); //将vec的大小调整为6,[10, 20, 0, 0, 0, 1]
vec.resize(3); //将vec的大小调整为3,[10, 20, 0]
- 字符串和数组
- 很多语言对字符串做了特殊的规定
- 在C语言中,把一个字符串存入一个数组时,也把结束符 '\0’存入数组,并以此作为该字符串是否结束
- 在C++中,提供一个string类,string类会提供 size接口,可以用来判断string类字符串是否结束,就不用’\0’来判断是否结束
- 基本操作上没有区别,但是 string提供更多的字符串处理的相关接口
思路:
主要考虑不用额外的辅助空间实现, 需要用到resize函数调整数组的大小
方法1: 使用额外空间
#include<bits/stdc++.h>
using namespace std;
int main(){
string str;
string result = "";
cin >> str;
for (int i = 0; i < str.length(); i++) {
if (str[i] >= '0' && str[i] <= '9') {
result += "number";
} else {
result += str[i];
}
}
cout << result << endl;
return 0;
}
方法2: 双指针法
状态: 需要细看, 实现存在问题
参考链接
步骤:
1.resize函数扩容
2.双指针从后往前遍历(备注: 从前往后为O(n^2)的时间复杂度, 而且需要额外空间存储)
#include<bits/stdc++.h>
using namespace std;
int main() {
string str;
cin >> str;
//1.遍历一次得需要替换的长度
int count = 0;
int size = str.length();
for (int i = 0; i < size; i++)
{
if (str[i] >= '0' && str[i] <= '9') {
count++;
}
}
//注意调整大小,减去原来的数字位
str.resize(size + count * 6 - count);
//从后往前遍历,时间复杂度为O(n)
//若从前往后遍历,时间复杂度为O(n^2)
int slow = str.length() - 1;
for (int fast = size - 1; fast >= 0; fast--)
{
if (str[fast] >= '0' && str[fast] <= '9')
{
str[slow--] = 'r';
str[slow--] = 'e';
str[slow--] = 'b';
str[slow--] = 'm';
str[slow--] = 'u';
str[slow--] = 'n';
}
else
{
str[slow--] = str[fast];
}
}
cout << str << endl;
}
151.翻转字符串里的单词
要求: 空间复杂度为O(1)
难点: 去除多余的空格
需要重复练习
//若fast指向不为' ', 则用while将该单词一次性录入
//slow除了在0时不插入空格外, 当每次进入s[fast] != ' '时,slow都插入空格
void removeExtraspace(string& s) {
int slow = 0;
for (int fast = 0; fast < s.size(); fast++) {
if (s[fast] != ' ') {
if (slow != 0) {
s[slow++] = ' ';
}
while (fast < s.size() && s[fast] != ' ') {
s[slow++] = s[fast++];
}
}
}
s.resize(slow);
}
//易理解版本
void removeExtraSpaces(string& s) {
int slow = 0, fast = 0;
while (fast < s.size() && s[fast] == ' ') {
fast++;
}
for (; fast < s.size(); fast++) {
if (s[fast] == ' ' && s[fast - 1] == s[fast]) {
continue;
}
else {
s[slow++] = s[fast];
}
}
if (s[slow - 1] == ' ') {
s.resize(slow - 1);
}
else {
s.resize(slow);
}
}
完整实现代码
void removeExtraSpaces(string& s) {
int slow = 0, fast = 0;
for (; fast < s.size(); fast++) {
if (s[fast] != ' ') {
if (slow != 0) {
s[slow++] = ' ';
}
while (s[fast] != ' ' && fast < s.size())
s[slow++] = s[fast++];
}
}
s.resize(slow);
}
string str;
int main() {
getline(cin, str);
removeExtraSpaces(str);
reverse(str.begin(), str.end());
int slow = 0;
int fast = 0;
for (;fast <= str.size(); fast++) {
if (fast < str.size() && str[fast] == ' ') {
reverse(str.begin() + slow, str.begin() + fast);
slow = fast + 1;
}
if (fast == str.size()) {
reverse(str.begin() + slow, str.end());
}
}
cout << str << endl;
}
卡码网:55.右旋转字符串
//最烂的写法
#include<bits/stdc++.h>
using namespace std;
int main() {
int k;
cin >> k;
cin.ignore();
string str;
cin >> str;
string str2 = "";
for (int i = str.length() - k; i < str.length(); i++) {
str2 += str[i];
}
for (int i = 0; i < str.length() - k; i++) {
str2 += str[i];
}
cout << str2 << endl;
return 0;
}
优化方法:
1.翻转
2.对子串再次翻转
#include<bits/stdc++.h>
using namespace std;
int main() {
int k;
cin >> k;
string str;
cin >> str;
reverse(str.begin(), str.end());
reverse(str.begin(), str.begin() + k); //前k个字串进行反转
reverse(str.begin() + k, str.end()); //剩余字串进行反转
cout << str << endl;
}