编写一个函数,其作用是将输入的字符串反转过来。输入字符串以字符数组 char[] 的形式给出。
不要给另外的数组分配额外的空间,你必须原地修改输入数组、使用 O(1) 的额外空间解决这一问题。
你可以假设数组中的所有字符都是 ASCII 码表中的可打印字符。
示例 1:
输入:[“h”,“e”,“l”,“l”,“o”]
输出:[“o”,“l”,“l”,“e”,“h”]
示例 2:
输入:[“H”,“a”,“n”,“n”,“a”,“h”]
输出:[“h”,“a”,“n”,“n”,“a”,“H”]
我的思路就是双指针,一前一后。
class Solution {
public:
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--;
}
}
};
很简单
给定一个字符串 s
和一个整数 k
,从字符串开头算起,每计数至 2k
个字符,就反转这 2k
字符中的前 k
个字符。
k
个,则将剩余字符全部反转。2k
但大于或等于 k
个,则反转前 k
个字符,其余字符保持原样。示例 1:
输入:s = "abcdefg", k = 2
输出:"bacdfeg"
示例 2:
输入:s = "abcd", k = 2
输出:"bacd"
我的思路是快慢指针,然后有一个bool值记录这个k之内该不该反转,然后处理一下临界情况就行。
class Solution {
public:
string reverseStr(string s, int k) {
int count=0;
bool rev=1;
for(int i=0;i<s.size();i++){
count++;
if(count==k&&rev){
int right=i;
int left=i+1-k;
while(left<right){
char tmp=s[left];
s[left]=s[right];
s[right]=tmp;
left++;
right--;
}
count=0;
rev=0;
}else if(count==k&&!rev){
count=0;
rev=1;
}else if(i==s.size()-1&&rev){
int right=i;
int left=i+1-count;
if(left<0)left=0;
while(left<right){
char tmp=s[left];
s[left]=s[right];
s[right]=tmp;
left++;
right--;
}
count=0;
rev=0;
}
}
return s;
}
};
给定一个字符串 s,它包含小写字母和数字字符,请编写一个函数,将字符串中的字母字符保持不变,而将每个数字字符替换为number。 例如,对于输入字符串 “a1b2c3”,函数应该将其转换为 “anumberbnumbercnumber”。
输入一个字符串 s,s 仅包含小写字母和数字字符。
打印一个新的字符串,其中每个数字字符都被替换为了number
a1b2c3
anumberbnumbercnumber
数据范围:
1 <= s.length < 10000。
做这道题之前,我了解了一下c++字符串操作的库函数
在C++中,字符串操作可以通过C风格字符串函数(位于
头文件)和C++的 std::string
类(位于
头文件)实现。以下是常用库函数和方法的分类介绍:
)C风格字符串以 \0
(空字符)结尾,操作时需注意内存管理和安全性。
strlen(const char* str)
返回字符串长度(不包含 \0
)。
char s[] = "Hello";
int len = strlen(s); // len = 5
strcpy(char* dest, const char* src)
将 src
复制到 dest
(需确保 dest
空间足够)。
更安全的替代:strncpy(dest, src, n)
(复制最多 n
个字符)。
char dest[10];
strcpy(dest, "Hello"); // dest = "Hello"
strcat(char* dest, const char* src)
将 src
追加到 dest
末尾。
更安全的替代:strncat(dest, src, n)
。
char dest[10] = "Hello";
strcat(dest, "!"); // dest = "Hello!"
strcmp(const char* s1, const char* s2)
比较字符串:
0
(相等)、>0
(s1 > s2)或 <0
(s1 < s2)。int result = strcmp("apple", "banana"); // result < 0
strchr(const char* str, int c)
返回字符 c
在 str
中首次出现的位置指针,未找到返回 nullptr
。
char* p = strchr("Hello", 'l'); // 指向第一个 'l' 的位置
strstr(const char* haystack, const char* needle)
返回子串 needle
在 haystack
中首次出现的位置指针。
char* p = strstr("Hello World", "World"); // 指向 "World"
strtok(char* str, const char* delim)
按分隔符 delim
分割字符串(线程不安全)。
char str[] = "a,b,c";
char* token = strtok(str, ","); // token依次为 "a", "b", "c"
memset(void* ptr, int value, size_t num)
将 ptr
指向的内存的前 num
字节设置为 value
。
char buffer[10];
memset(buffer, 0, sizeof(buffer)); // 全部初始化为0
memcpy(void* dest, const void* src, size_t num)
从 src
复制 num
字节到 dest
(不处理重叠区域)。
char src[] = "Copy";
char dest[5];
memcpy(dest, src, 5); // dest = "Copy"
std::string
类(
)std::string
自动管理内存,更安全且功能丰富。
string(const char* s)
从C风格字符串构造。
std::string s = "Hello";
assign()
赋值操作。
s.assign("World");
append()
/ +=
追加字符串。
s.append("!"); // s = "Hello!"
s += "!!"; // s = "Hello!!!"
insert(size_t pos, const string& str)
在指定位置插入字符串。
s.insert(5, " World"); // "Hello World"
replace(size_t pos, size_t len, const string& str)
替换子串。
s.replace(6, 5, "There"); // "Hello There"
erase(size_t pos = 0, size_t len = npos)
删除子串。
s.erase(5, 6); // s = "Hello"
find(const string& str, size_t pos = 0)
查找子串,返回起始索引(未找到返回 string::npos
)。
size_t idx = s.find("World"); // idx = 6
substr(size_t pos = 0, size_t len = npos)
提取子串。
std::string sub = s.substr(6, 5); // sub = "World"
compare(const string& str)
比较字符串(类似 strcmp
)。
int res = s.compare("Hello"); // 0(相等)
c_str()
返回C风格字符串(以 \0
结尾)。
const char* cstr = s.c_str();
stoi()
, stol()
, stof()
将字符串转换为数值。
int num = std::stoi("123"); // num = 123
std::getline()
读取一行输入(可处理空格)。
std::string input;
std::getline(std::cin, input);
std::to_string()
将数值转换为字符串。
std::string num_str = std::to_string(42); // "42"
std::string_view
(C++17)
提供对字符串的非拥有视图,避免拷贝。
std::string_view view = "Hello";
strcpy
、strcat
等易导致缓冲区溢出,建议使用 strncpy
、strncat
或优先选择 std::string
。std::string
自动管理。std::string
操作可能涉及动态内存分配,高频操作时需注意效率。推荐实践:优先使用 std::string
和 C++标准库,避免直接操作C风格字符串,以提高代码安全性和可维护性。
我的代码实现:
#include
#include
using namespace std;
int main(){
string s;
cin>>s;
for(int i=0;i<s.size();i++){
if(s[i]>='0'&&s[i]<='9'){
//if(i>0&&s[i-1]>='0'&&s[i-1]<='9')continue;
cout<<"number";
}else{
cout<<s[i];
}
}
}
很简单
我的做法是直接输出,相当于使用了额外的内存空间,代码随想录上面使用的双指针法:
先扩充好空间,快指针探路,慢指针填充;
#include
using namespace std;
int main() {
string s;
while (cin >> s) {
int sOldIndex = s.size() - 1;
int count = 0; // 统计数字的个数
for (int i = 0; i < s.size(); i++) {
if (s[i] >= '0' && s[i] <= '9') {
count++;
}
}
// 扩充字符串s的大小,也就是将每个数字替换成"number"之后的大小
s.resize(s.size() + count * 5);
int sNewIndex = s.size() - 1;
// 从后往前将数字替换为"number"
while (sOldIndex >= 0) {
if (s[sOldIndex] >= '0' && s[sOldIndex] <= '9') {
s[sNewIndex--] = 'r';
s[sNewIndex--] = 'e';
s[sNewIndex--] = 'b';
s[sNewIndex--] = 'm';
s[sNewIndex--] = 'u';
s[sNewIndex--] = 'n';
} else {
s[sNewIndex--] = s[sOldIndex];
}
sOldIndex--;
}
cout << s << endl;
}
}
从后往前