力扣对应链接:LCR 122. 路径加密 - 力扣(LeetCode)
牛客对应链接:替换空格_牛客题霸_牛客网 (nowcoder.com)
核心考点 :字符串相关,特性观察,临界条件处理。
一、《剑指Offer》内容
二、分析问题
虽然是替换问题,但是生成的字符串整体变长了。因替换内容比被替换内容长,所以一定涉及到字符串中字符的移动问题。移动方向一定是向后移动,所以现在的问题无非是移动多少的问题。因为是 ' ' -> "%20",是 1 换 3,所以可以先统计原字符串中空格的个数(设为 n),然后可以计算出新字符串的长度。所以,new_length = old_length + 2*n最后,定义新老索引(或者指针),各自指向新老空间的结尾,然后进行 old->new 的移动。如果是空格,就连续放入“%20”,其他平移即可。当然,C++ 有很多容器,也可以从前往后通过开辟空间来进行解决,也就是使用空间来换取时间。但是,最好不要在面试场景下这么做。
三、代码
//力扣上的这道题目是1换1,不需要扩充数组
class Solution {
public:
string pathEncryption(string path) {
for(int i=0; i<path.size(); i++)
if(path[i]=='.')
path[i]=' ';
return path;
}
};
//牛客网上的这道题目和原题也不太一样,这里传入的是string,原题是char*
class Solution {
public:
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param s string字符串
* @return string字符串
*/
string replaceSpace(string s) {
string res;
for(int i=0; i<s.size(); i++)
{
if(s[i]==' ') res+="%20";
else res+=s[i];
}
return res;
}
};
//下面写法尽量贴近原题(注意:原题是char*,C++要考虑'\0')
class Solution {
public:
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param s string字符串
* @return string字符串
*/
string replaceSpace(string s) {
if(s.size()==0) return s;
int cnt=0; //记录空格个数
for(auto c:s)
{
if(c==' ')
cnt++;
}
int old_end=s.size()-1;
for(int i=0; i<cnt*2; i++)
s.push_back(' ');
int new_end=s.size()-1;
while(old_end>=0 && new_end>=0)
{
if(s[old_end]==' ')
{
s[new_end--]='0';
s[new_end--]='2';
s[new_end--]='%';
old_end--;
}
else
{
s[new_end--]=s[old_end--];
}
}
return s;
}
};
四、扩展
有两个排序的数组 A1 和 A2,内存在 A1 的末尾有足够多的空余空间容纳 A2。请实现一个函数,把 A2 中的所有数字插入到 A1 中并且所有的数字是排序的。
和前面的例题一样,首先想到的办法可能是从前到尾复制数字,但这样就会出现多次复制一个数字的情况。
更好的办法是从尾到头比较 A1 和 A2 中的数字,并把较大的数字赋值到 A1 的合适位置。
C 库函数中内存拷贝 memmove() 函数与此题有共同点,函数功能就是:将起始地址 src 且长度为 count 的内存拷贝到起始地址 dst 处,并返回 dst,返回是为了实现链式表达式。
函数原型为:void* __cdecl memmove(void *dst, const void *src, size_t count;
五、举一反三
合并两个数字(包括字符串)时,如果从前往后复制每个数字(或字符)需要重复移动数字(或字符)多次,那么我们可以考虑从后往前复制,这样就能减少移动的次数,从而提高效率。