题目:实现一个函数,把字符串中的每个空格替换成”%20”,例如输入”we are happy”则输出”we20%are20% happy”;
常规的思路:
我们遍历这个字符串,没遇到一个空格的时候我们把1个空格替换成3个空格,也就是空格后面的字符向后移两个字节,否则就会把后面的字符覆盖了;
如:我们从头打到尾把”we are happy”中的一个空格替换成两个空格
方案一:遇到空格向后挪两位然后把%20拷贝进去,继续遍历字符串,遇到空格做相同的操作,直到字符串尾.
我们发现方案一的做法时间复杂度太高,没遇到空格都要挪动数据,当字符串的长度很长时,效率会很慢,假如一个长度为n的字符串,对于每个空字符串,需要向后移动O(n)个字符,整体来说时间复杂度就是O(n^2);
方案二:
从后向前遍历这个字符串,分别用两个指针p1表示替换前的字符串的末尾.指针p2表示替换后字符串的末尾,.然后指针p1向前移动,逐个把字符拷贝到p2所指的位置,遇到空格停止,遇到第一个空格p1向前移动1格,在p2之前插入”%20”,继续向前遍历,知道所有空格被替换,最后p1和p2指向同一位置.
实现:
void ReplaceBlack(char *str, int len)
{
assert(str != NULL&&len > 0);
//OldLend表示原长度
int OldLen = 0;
int CountBlack = 0;//统计空格数
int i = 0;
while (str[i] != '\0')
{
++OldLen;
if (str[i] == ' ')
++CountBlack;//空格数
++i;
}
int NewLen = OldLen + 2 * CountBlack;//新的长度
int IndexOld = OldLen;
int IndexNew = NewLen;
while (IndexOld>=0&&IndexOld>IndexNew)
{
//IndexOld遇到空格停下来,IndexNew前移替换
if (str[IndexOld] == ' ')
{
str[IndexNew--] = '%';
str[IndexNew--] = '0';
str[IndexNew--] = '2';
}
else
{
//把原来的字符串拷贝到新空间
str[IndexNew--] = str[IndexOld];
}
--IndexOld;
}
}
同样的如果两个排序数组A1和A2,内存在A1尾部有足够的剩余空间容纳A2,实现一个函数把A2的数据插入到A1当中并且是有序的;
方法和前面类似,如果从头到尾拷贝数据,会多拷贝一次,如何从后向前拷贝效率会更高.