需求描述
给定一个字符串,在字符串中查找某一个特定字符(如空格)然后将其替换为新的字符串(如%20),加入有字符串"This is a demo",
经过替换之后的字符串应该变为"This%20is%20a%demo."
。
算法分析
这个需求也算是相当常见了,但是越简单的问题就越要搞清楚,最好的时间和空间复杂度是什么,同时也要思考透过这个简单的问题,能够帮助我们学习到什么定式问题解决策略,以丰富我们解决问题的思路。
很多人一看到就会想到这就是一个字符串替换,直接从前往后查找然后替换就行了,这样的确可以,但是同时也是忽视了数组的移动问题,因为长度的改变,导致了在一次次的替换过程中替换内容后面的部分被频繁的后移,引发较大的开销,如果是不可修改的字符串类型的话则相当于导致了多次拷替换拷贝。
所以我们的目标就变成了如何减少数组移动的开销,这个解决思路应该很容易想到,==这个思路也是处理数组(字符数组)问题的一个定式策略,在很多数组的移动问题中能够减少开销。==我们可以一次性确定好每个元素被移动到的最终位置,然后将元素直接移动到自己的位置上即可,显然在本例中,每一个元素后移的位置就是
个位置,所以移动后的数组长度
,如果数组的长度不够,我们则需要开辟一次空间。我们可以从后往前拷贝,不断的把k位置上的元素赋值给l,遇到一个非空格字符,
和
分别往前挪一个位置,遇到一个空格,
往前挪一个位置,
往前挪三个位置。最终当k=l时,循环结束。
统计有多少个空格需要对数组扫描一遍,时间复杂度是
,替换过程中,相当于把数组移动了一遍,移动和写入的元素是
的,所以时间复杂度是
。
测试了python字符串的替换函数,发现函数的执行时间是线性的,推测python的字符串替换采取的就是方式。需要注意到这种确定好位置再移动的思想在其他数组问题中可能也会遇到,同时要注意到如果是两个字符串之间的替换,也需要会分析算法复杂度。在这里补充一句,字符串的匹配KMP算法时间复杂度是
。
空格替换代码实现
void replaceSpace(char* str, int length) {
if (str == NULL || length <= 0)
return;
int count = 0;
int len = 0;
// 统计空格的个数
while (str[len])
{
if (str[len] == ' ')
count++;
len++;
}
int newlen = len + count * 2;
if (length < newlen) {
//这里执行拷贝
return;
}
int k = len;
int l = newlen;
while (l >= 0 && k >= 0)
{
if (str[k] == ' ')
{
str[l--] = '0';
str[l--] = '2';
str[l--] = '%';
}
else {
str[l--] = str[k];
}
k--;
}
}