剑指offer字符串面试题 替换空格
题目:
力扣:剑指 Offer 05. 替换空格
牛客网:编程题 空格替换
力扣:leetcode面试题 01.03. URL化
请实现一个函数,将一个字符串中的每个空格替换成“%20”。例如,当字符串为We Are Happy.则经过替换之后的字符串为We%20Are%20Happy。
在网络编程中,如果URL参数中含有特殊字符,如空格、#等,则可能导致服务器端无法获得正确的参数值。我们需要将这些特殊符号转换成服务器可以识别的字符。转换的规则是在°%后面跟上ASCII码的两位十六进制的表示。比如空格的ASCII码是32,即十六进制的0x20,因此空格被替换成"%20"。再比如#的ASCII码为35,即十六进制的0x23,它在URL中被替换为"%23"。
看到这个题目,我们首先应该想到的是原来一个空格字符, 替换之后变成’%’、'2’和’0这 3个字符,因此字符串会变长。如果是在原来的字符串上进行替换,就有可能覆盖修改在该字符串后面的内存。如果是创建新的字符串并在新的字符串上进行替换,那么我们可以自己分配足够多的内存。由于有两种不同的解决方案,我们应该向面试官问清楚,让他明确告诉我们他的需求。假设面试官让我们在原来的字符串上进行替换,并且保证输入的字符串后面有足够多的空余内存。
————《剑指offer》 p51
时间复杂度为O(n²)的算法,
//牛客网解题代码
class Solution {
public:
void replaceSpace(char *str,int length) {
if (str == NULL && length < 0){
return;
}
for (int i = 0; i < length; i++){
if (str[i] == ' '){
length += 2;
int newlength = length;
while (newlength - i -2){
str[newlength] = str[newlength - 2];
newlength--;
}
str[i] = '%';
str[i + 1] = '2';
str[i + 2] = '0';
}
}
}
};
运行截图:
虽然这种方法思路最为简单粗暴而且在牛客可以通过,但是在本地运行时就会发现字符数组存储空间不足出现周围栈空间被破坏的错误(栈溢出)。所以不推荐。
时间复杂度O(n)的算法
牛客解题源码
https://github.com/zhedahht/CodingInterviewChinese2/blob/master/05_ReplaceSpaces/ReplaceSpaces.cpp
class Solution {
public:
void replaceSpace(char *str,int length) {
if (str == NULL && length <= 0){ //如果S指向空或者为空串
return;
}
int cnt = 0;
for (int i = 0; i < length; i++){
if (str[i] == ' '){
cnt++; //统计字符串空格数
}
}
if (!cnt){ //如果没有空格
return;
}
int newlength = cnt * 2 + length; // newlength 为把空格替换成'%20'之后的长度
//从后往前替换
while (length+1){
if (str[length] == ' '){ //替换空格
str[newlength--] = '0';
str[newlength--] = '2';
str[newlength--] = '%';
}
else{
str[newlength--] = str[length]; //(末尾"\0")
}
length--;
}
}
};
测试用例:
● 输入的字符串中包含空格(空格位于字符串的最前面;空格位于字符串的最后面;空格位于字符串的中间;字符串中有连续多个空格)。
● 输入的字符串中没有空格。
● 特殊输入测试(字符串是一个nullptr指针;字符串是一个空字符串;字符串只有一个空格字符;字符串中有连续多个空格)。
力扣解题源码
URL化
与上面唯一不同就是测试用例字符串会在末尾 ‘\0’ 前存在空格,而尾部空格可能本判定为无效字符串不统计在length中,所以需要我们给字符串末尾手动添加 ‘\0’
char* replaceSpaces(char* S, int length){
if (NULL == S || length < 0){ //如果S指向空或者为空串
return NULL;
}
int count = 0;
for (int i = 0; i < length; i++){
if (S[i] == ' '){
count++; //统计字符串空格数
}
}
if (!count){ //如果没有空格
return S;
}
int newlen = count * 2 + length; //计算替换后的新长度
S[newlen--] = '\0'; //(末尾'\0')
int end = length - 1; // 字符串末尾
//从后往前替换
while (end+1){
if (S[end] == ' '){ //替换空格为"%20"
S[newlen--] = '0';
S[newlen--] = '2';
S[newlen--] = '%';
end--;
}
else{
S[newlen--] = S[end--];
}
}
return S;
}
剑指 Offer 05. 替换空格
leetcode测试用例比牛客稍严格,而且这题函数参数不同,需要自己malloc开辟新空间
char* replaceSpace(char* s){
if (NULL == s){ //如果S指向空或者为空串
return NULL;
}
int length = strlen(s);
int count = 0;
for (int i = 0; i < length; i++){
if (s[i] == ' '){
count++; //统计字符串空格数
}
}
if (!count){ //如果没有空格
return s;
}
int newlen = count * 2 + length; //计算替换后的新长度
char* str = (char*)malloc(sizeof(char)*(newlen + 1)); //申请新数组
if (NULL == str){
assert(0);
return NULL;
}
int newend = newlen - 1;
//从后往前替换
while (length){
length--;
if (s[length] == ' '){ //替换空格
str[newend--] = '0';
str[newend--] = '2';
str[newend--] = '%';
}
else{
str[newend--] = s[length];
}
}
str[newlen] = '\0';
free(s); //释放旧数组
return str;
}