剑指Offer_面试题04_替换空格

来源:互联网 发布:中国的地位知乎 编辑:程序博客网 时间:2024/06/05 10:48

题目:请实现一个函数,将一个字符串中的空格替换成“%20”。例如,当字符串为We Are Happy.则经过替换之后的字符串为We%20Are%20Happy。

不好解法:遍历,找空格,插“%20”,其中插入包括先移动,后赋值。这样的解法时间复杂度o(n^2)


优秀解法:遍历一遍字符串,统计空格,计算出插入后的总长度。然后从字符串的后面开始复制和替换,如此,时间复杂度o(n)



#include <stdio.h>#include <iostream>//param length 数组长度bool ReplaceBlank(char string[], int length){if (string == NULL || length <= 0)return false;int p = 0;    //原字符串结尾int q = 0;    //填充后的结尾int blankCount = 0;while (string[p] != '\0'){if (string[p] == ' ')blankCount++;++p;}q = p + 2 * blankCount;if (q > length - 1)    //越界return false;while (p >= 0 && p < q){if (string[p] == ' '){string[q--] = '0';string[q--] = '2';string[q--] = '%';--p;continue;}string[q--] = string[p--];}return true;}int main(){char string[1024] = "we are happy!";char string2[1024] = " haha ha ";printf("%s\n", string);if (ReplaceBlank(string, 1024))printf("%s\n", string);elseprintf("error\n");printf("%s\n", string2);if (ReplaceBlank(string2, 1024))printf("%s\n", string2);elseprintf("error\n");system("pause");return 0;}

拓展题:有两个排序数组A1和A2,内存在A1的末尾有足够多的多余空间容纳A2。请实现一个函数,把A2中的所有数字插入到A1中,并且所有数字有序。

解题思维与上题类似,如果遍历A2插入到A1中则会造成多次移动A1中的元素,时间复杂度o(n^2)。

如果先计算出插入后的长度,然后从A1和A2的末尾开始比较,谁大把谁插入新的末尾,以此类推一直到A1或A2遍历结束,所有元素移动一次,时间复杂度O(n)

#include <stdio.h>#include <iostream>using namespace std;//把一个有序数组插入到另一个有序数组中o(n)解法. b插到a中void OredrArrayInsert(double *a, double *b, int len_a, int len_b){int len = len_a + len_b;    //插入后的长度while (len > 0 && len_a > 0 && len_b > 0){if (a[len_a - 1] > b[len_b - 1]){a[len - 1] = a[len_a - 1];--len_a;--len;}else {a[len - 1] = b[len_b - 1];--len_b;--len;}}//a拷贝完全,b还没有拷贝完while (len > 0 && len_b > 0){a[len - 1] = b[len_b - 1];--len;--len_b;}//b拷贝完全,a还没有拷贝完while (len > 0 && len_a > 0){a[len - 1] = a[len_a - 1];--len;--len_a;}}void printArray(double *a, int len){for (int i = 0; i < len; i++)cout << a[i] << ",";cout << endl;}int main(){double R[] = {12,34,20,15,9,25,27,13};cout << sizeof(R) / sizeof(double) << endl;QuickSort(R, 0, 7);for (int k = 0; k < 8; k++)cout << R[k] << " ";cout << endl;double a[1024];for (int i = 0; i < 10; i++)a[i] = i;double b[] = {2,3,4,9,15,22,30,70};printArray(a,10);printArray(b,8);//printArray(a, 17);OredrArrayInsert(a, b, 10, 8);printArray(a, 18);system("pause");return 0;}


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