LeetCode 344 反转字符串
编写一个函数,其作用是将输入的字符串反转过来。输入字符串以字符数组 s
的形式给出。
不要给另外的数组分配额外的空间,你必须原地修改输入数组、使用 O(1) 的额外空间解决这一问题。
示例 1:
输入:s = ["h","e","l","l","o"] 输出:["o","l","l","e","h"]
示例 2:
输入:s = ["H","a","n","n","a","h"] 输出:["h","a","n","n","a","H"]
思路:这道题也是使用双指针法,比链表简单很多,只需要直接交换两个指针所指的数据即可
class Solution {
public:
void reverseString(vector<char>& s) {
for (int i = 0, j = s.size() - 1; i <= j; i++, j--) {
swap(s[i],s[j]);
}
}
};
LeetCode541. 反转字符串II
给定一个字符串 s
和一个整数 k
,从字符串开头算起,每计数至 2k
个字符,就反转这 2k
字符中的前 k
个字符。
- 如果剩余字符少于
k
个,则将剩余字符全部反转。 - 如果剩余字符小于
2k
但大于或等于k
个,则反转前k
个字符,其余字符保持原样。
示例 1:
输入:s = "abcdefg", k = 2 输出:"bacdfeg"
示例 2:
输入:s = "abcd", k = 2 输出:"bacd"
思路:每隔2k个字符循环一次
class Solution {
public:
string reverseStr(string s, int k) {
int n = s.size()/2/k;
cout << n << endl;int a = 0;int b = k-1;
for(int i = 0; i < n;i++){
for (int y = a, z = b; y <= z; y++, z--) {
swap(s[y],s[z]);
}
cout << s << endl;
a += 2*k;
b += 2*k;
}
int mod = s.size() % (2*k);
cout << mod << endl;
if(mod < k){
for (int y = n*2*k, z = y + mod - 1; y <= z; y++, z--) {
swap(s[y],s[z]);
}
}
else{
for (int y = n*2*k, z = y + k - 1; y <= z; y++, z--) {
swap(s[y],s[z]);
}
}
return s;
}
};
较为简便的思路:把交换用reverse函数来写
class Solution {
public:
string reverseStr(string s, int k) {
for (int i = 0; i < s.size(); i += (2 * k)) {
// 1. 每隔 2k 个字符的前 k 个字符进行反转
// 2. 剩余字符小于 2k 但大于或等于 k 个,则反转前 k 个字符
if (i + k <= s.size()) {
reverse(s.begin() + i, s.begin() + i + k );
} else {
// 3. 剩余字符少于 k 个,则将剩余字符全部反转。
reverse(s.begin() + i, s.end());
}
}
return s;
}
};
LeetCode 54 替换数字
给定一个字符串 s,它包含小写字母和数字字符,请编写一个函数,将字符串中的字母字符保持不变,而将每个数字字符替换为number。 例如,对于输入字符串 "a1b2c3",函数应该将其转换为 "anumberbnumbercnumber"。
输入描述
输入一个字符串 s,s 仅包含小写字母和数字字符。
输出描述
打印一个新的字符串,其中每个数字字符都被替换为了number
输入示例
a1b2c3
输出示例
anumberbnumbercnumber
思路:
首先扩充数组到每个数字字符替换成 "number" 之后的大小。
例如 字符串 "a5b" 的长度为3,那么 将 数字字符变成字符串 "number" 之后的字符串为 "anumberb" 长度为 8。
如图:
然后从后向前替换数字字符,也就是双指针法,过程如下:i指向新长度的末尾,j指向旧长度的末尾。
不从前往后填充是因为,每次添加元素都要将添加元素之后的所有元素整体向后移动。
#include <iostream>
using namespace std;
int main(){
string s;
while (cin >> s) {
int count = 0;
for(int i = 0; i < s.size();i++){
if(s[i] >= '0'&& s[i] <= '9'){
count++;
}
}
int snew_length = s.size() + 5 * count;
string snew(snew_length,'0');
for(int i = s.size() - 1,j = snew_length - 1;0 <= i;){
if(s[i] >= 'a'&& s[i] <= 'z'){
snew[j] = s[i];
i--;
j--;
}
else{
snew[j] = 'r';
snew[j - 1] = 'e';
snew[j - 2] = 'b';
snew[j - 3] = 'm';
snew[j - 4] = 'u';
snew[j - 5] = 'n';
j -= 6;
i--;
}
}
cout << snew << endl;
}
}
LeetCode 151.反转字符串里的单词
给你一个字符串 s
,请你反转字符串中 单词 的顺序。
单词 是由非空格字符组成的字符串。s
中使用至少一个空格将字符串中的 单词 分隔开。
返回 单词 顺序颠倒且 单词 之间用单个空格连接的结果字符串。
注意:输入字符串 s
中可能会存在前导空格、尾随空格或者单词间的多个空格。返回的结果字符串中,单词间应当仅用单个空格分隔,且不包含任何额外的空格。
示例 1:
输入:s = "the sky is blue
" 输出:"blue is sky the
"
示例 2:
输入:s = " hello world " 输出:"world hello" 解释:反转后的字符串中不能存在前导空格和尾随空格。
示例 3:
输入:s = "a good example" 输出:"example good a" 解释:如果两个单词间有多余的空格,反转后的字符串需要将单词间的空格减少到仅有一个。
思路: 先去除多余的空格,然后将整个字符串都进行反转,再将每个单词重新反转回来,反转每个单词的时候,是通过有无空格来判断是不是到下一个单词了。
删除空格的思路和先前删除元素的题思路一样,如果快指针指到非空格,再将值赋给慢指针,一直重复道赋值完一整个单词之后,再出循环。但是因为两个单词之间需要一个空格,所以要再增加一个判断,就是当慢指针指向的不是第一个单词的开头,而是指向第一个单词的后面时,加一个空格。
class Solution {
public:
void reverse(string& s, int start, int end){
for (int i = start, j = end; i < j; i++, j--) {
swap(s[i], s[j]);
}
}
void removeExtraSpaces(string& s) {
int slow = 0;
for (int i = 0; i < s.size(); ++i) {
if (s[i] != ' ' && slow != 0) s[slow++] = ' ';
while (i < s.size() && s[i] != ' ') {
s[slow++] = s[i++];
}
}
s.resize(slow);
}
string reverseWords(string s) {
removeExtraSpaces(s);
reverse(s, 0, s.size() - 1);
int start = 0;
for (int i = 0; i <= s.size(); ++i) {
if (i == s.size() || s[i] == ' ') {
reverse(s, start, i - 1);
start = i + 1;
}
}
return s;
}
};
LeetCode 55 右旋转字符串
字符串的右旋转操作是把字符串尾部的若干个字符转移到字符串的前面。给定一个字符串 s 和一个正整数 k,请编写一个函数,将字符串中的后面 k 个字符移到字符串的前面,实现字符串的右旋转操作。
例如,对于输入字符串 "abcdefg" 和整数 2,函数应该将其转换为 "fgabcde"。
输入描述
输入共包含两行,第一行为一个正整数 k,代表右旋转的位数。第二行为字符串 s,代表需要旋转的字符串。
输出描述
输出共一行,为进行了右旋转操作后的字符串。
输入示例
2
abcdefg
输出示例
fgabcde
思路:采用先整体倒叙再局部倒叙
ps:reverse函数的反转不包括最后一位。 reverse(start, end)