【面试题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         }

【举一反三】

合并两个数组(包括字符串)时,如果从前往后复制每个数字(或字符)需要重复移动数字(或字符)多次,那么我们可以考虑从后往前复制,这样就减少了移动的次数,从而提高效率。

posted @ 2015-09-10 10:40  叫我霍啊啊啊  阅读(157)  评论(0编辑  收藏  举报