【面试题4】替换空格
【题目描述】
请实现一个函数,把字符串中的每个空格替换成“%20”。例如输入“We are happy.”,则输出“We%20are%20happy.”。
【解决方案】
1. 时间复杂度为O(n^2)
因为空格替换成“%20”之后,增加了两个字符,可能会造成原来的字符串放不下修改之后的字符串,需要遍历原来的字符串,根据空格的数量来新建一个容量足够的新数组。
最容易想到的办法,从前往后依次遍历,遇到空格则把其后所有字符往后移动两位。
假设字符串的长度是n,对每个空格字符,需要移动后面的0(n)个字符,因此对含有0(n)个空格字符的字符串而言总的时间效率是0(n^2)。
我们可以尝试从后往前遍历。
2. 时间复杂度为O(n)
设置两个指针为p1,p2,分别放到原始字符串的末尾和新字符串的末尾,从后往前,直到p1==p2,则证明替换已经完成。如图,
我的代码实现,仅供参考:
1 public string ReplaceBlank(string str) 2 { 3 if (str == null) 4 return null; 5 6 int length = str.Length, spaceNum = 0; 7 8 foreach (char c in str) 9 { 10 if (c == ' ') 11 spaceNum++; 12 } 13 14 char[] newStr = new char[length + spaceNum * 2]; 15 16 int pOld = length - 1, pNew = newStr.Length - 1; 17 18 while (pOld >= 0) 19 { 20 if (str[pOld] != ' ') 21 { 22 newStr[pNew] = str[pOld]; 23 } 24 else 25 { 26 newStr[pNew - 2] = '%'; 27 newStr[pNew - 1] = '2'; 28 newStr[pNew] = '0'; 29 pNew -= 2; 30 } 31 pOld--; 32 pNew--; 33 } 34 35 return new string(newStr); 36 }
【本题扩展】
有两个排序数组A1和A2,内存是A1的末尾有足够多的空余空间能够容纳A2。请实现一个函数,把A2中的所有数字插入到A1中并且所有的数字是排序的。
和前面的例题一样,很多人首先想到的办法是在A1中从头到尾复制数字,但是这样就会出现多次复制一个数字的情况。更好的办法是从尾到头比较A1和A2中的数字,并把比较大的数字复制到A1中的合适位置。
我的代码实现,仅供参考:
1 public void MergeSortedArray(int?[] arrA, int?[] arrB) 2 { 3 //lenA表示arrA不为null部分的长度 4 int lenA = 0, lenB = arrB.Length; 5 6 foreach (int? num in arrA) 7 { 8 if (num != null) 9 lenA++; 10 else 11 break; 12 } 13 14 int pA = lenA - 1, pB = lenB - 1; 15 16 while (pB >= 0) 17 { 18 if (arrA[pA] > arrB[pB]) 19 { 20 arrA[pA + pB + 1] = arrA[pA]; 21 pA--; 22 } 23 else 24 { 25 arrA[pA + pB + 1] = arrB[pB]; 26 pB--; 27 } 28 } 29 }
【举一反三】
合并两个数组(包括字符串)时,如果从前往后复制每个数字(或字符)需要重复移动数字(或字符)多次,那么我们可以考虑从后往前复制,这样就减少了移动的次数,从而提高效率。