一、题目:替换空格

题目:请实现一个函数,把字符串中的每个空格替换成"%20"。例如输入“We are happy.”,则输出“We%20are%20happy.”。 

  在网络编程中,如果URL参数中含有特殊字符,如空格、'#'等,可能导致服务器端无法获得正确的参数值。我们需要将这些特殊符号转换成服务器可以识别的字符。转换的规则是在'%'后面跟上ASCII码的两位十六进制的表示。比如空格的ASCII码是32,即十六进制的0x20,因此空格被替换成"%20"。再比如'#'的ASCII码为35,即十六进制的0x23,它在URL中被替换为"%23"。

二、解题思路

2.1 O(n2)的解法

  最直观的做法是从头到尾扫描字符串,每一次碰到空格字符的时候做替换。由于是把1个字符替换成3个字符,我们必须要把空格后面所有的字符都后移两个字节,否则就有两个字符被覆盖了。下图展示了从前往后把字符串中的空格替换成'%20'的过程:

  假设字符串的长度是n。对每个空格字符,需要移动后面O(n)个字符,因此对含有O(n)个空格字符的字符串而言总的时间效率是O(n2)。

2.2 O(n)的解法

  Step1.先遍历一次字符串,这样就能统计出字符串中空格的总数,并可以由此计算出替换之后的字符串的总长度。

  以前面的字符串"We arehappy."为例,"We are happy."这个字符串的长度是14(包括结尾符号'\0'),里面有两个空格,因此替换之后字符串的长度是18。

  Step2.从字符串的后面开始复制和替换。

  准备两个指针,P1和P2。P1指向原始字符串的末尾,而P2指向替换之后的字符串的末尾。接下来向前移动指针P1,逐个把它指向的字符复制到P2指向的位置,直到碰到第一个空格为止。接着向前复制,直到碰到第二、三或第n个空格。

  从上面的分析我们可以看出,所有的字符都只复制(移动)一次,因此这个算法的时间效率是O(n),比第一个思路要快。

三、解决问题

3.1 代码实现

    public static void ReplaceBlank(char[] target, int maxLength)
{
if (target == null || maxLength <= )
{
return;
} // originalLength 为字符串target的实际长度
int originalLength = ;
int blankCount = ;
int i = ; while (target[i] != '\0')
{
originalLength++;
// 计算空格数量
if (target[i] == ' ')
{
blankCount++;
}
i++;
} // newLength 为把空格替换成'%20'之后的长度
int newLength = originalLength + * blankCount;
if (newLength > maxLength)
{
return;
} // 设置两个指针,一个指向原始字符串的末尾,另一个指向替换之后的字符串的末尾
int indexOfOriginal = originalLength;
int indexOfNew = newLength; while (indexOfOriginal >= && indexOfNew >= )
{
if (target[indexOfOriginal] == ' ')
{
target[indexOfNew--] = '';
target[indexOfNew--] = '';
target[indexOfNew--] = '%';
}
else
{
target[indexOfNew--] = target[indexOfOriginal];
} indexOfOriginal--;
}
}

3.2 单元测试

  由于C#语言的特殊性,这里在测试初始化时做了一些特殊处理操作:

        const int maxLength = ;
char[] target = new char[maxLength];
// Pre-Test
[TestInitialize]
public void ReplaceBlankInitialize()
{
for (int i = ; i < maxLength; i++)
{
target[i] = '\0';
}
} public char[] GenerateNewTarget()
{
int length = ;
for (int i = ; i < maxLength && target[i] != '\0'; i++)
{
length++;
} char[] newTarget = new char[length]; for (int i = ; i < maxLength && target[i] != '\0'; i++)
{
newTarget[i] = target[i];
} return newTarget;
}

  (1)Test1:空格在句子中间

        // Test1:空格在句子中间
[TestMethod]
public void ReplaceBlankTest1()
{
// "hello world"
target[] = 'h';
target[] = 'e';
target[] = 'l';
target[] = 'l';
target[] = 'o';
target[] = ' ';
target[] = 'w';
target[] = 'o';
target[] = 'r';
target[] = 'l';
target[] = 'd'; Program.ReplaceBlank(target, maxLength);
string compared = new string(this.GenerateNewTarget());
string expected = "hello%20world"; Assert.AreEqual(compared, expected);
}

  (2)Test2:空格在句子开头

        // Test2:空格在句子开头
[TestMethod]
public void ReplaceBlankTest2()
{
// " helloworld"
target[] = ' ';
target[] = 'h';
target[] = 'e';
target[] = 'l';
target[] = 'l';
target[] = 'o';
target[] = 'w';
target[] = 'o';
target[] = 'r';
target[] = 'l';
target[] = 'd'; Program.ReplaceBlank(target, maxLength);
string compared = new string(this.GenerateNewTarget());
string expected = "%20helloworld"; Assert.AreEqual(compared, expected);
}

  (3)Test3:空格在句子末尾

        // Test3:空格在句子末尾
[TestMethod]
public void ReplaceBlankTest3()
{
// "helloworld "
target[] = 'h';
target[] = 'e';
target[] = 'l';
target[] = 'l';
target[] = 'o';
target[] = 'w';
target[] = 'o';
target[] = 'r';
target[] = 'l';
target[] = 'd';
target[] = ' '; Program.ReplaceBlank(target, maxLength);
string compared = new string(this.GenerateNewTarget());
string expected = "helloworld%20"; Assert.AreEqual(compared, expected);
}

  (4)Test4:连续有两个空格

        // Test4:连续有两个空格
[TestMethod]
public void ReplaceBlankTest4()
{
// "helloworld "
target[] = 'h';
target[] = 'e';
target[] = 'l';
target[] = 'l';
target[] = 'o';
target[] = ' ';
target[] = ' ';
target[] = 'w';
target[] = 'o';
target[] = 'r';
target[] = 'l';
target[] = 'd'; Program.ReplaceBlank(target, maxLength);
string compared = new string(this.GenerateNewTarget());
string expected = "hello%20%20world"; Assert.AreEqual(compared, expected);
}

  (5)Test5:传入NULL

        // Test5:传入NULL
[TestMethod]
public void ReplaceBlankTest5()
{
target = null;
Program.ReplaceBlank(target, );
char[] expected = null; Assert.AreEqual(target, expected);
}

  (6)Test6:传入内容为空的字符串

        // Test6:传入内容为空的字符串
[TestMethod]
public void ReplaceBlankTest6()
{
// ""
Program.ReplaceBlank(target, maxLength);
string compared = new string(this.GenerateNewTarget());
string expected = ""; Assert.AreEqual(compared, expected);
}

  (7)Test7:传入内容为一个空格的字符串

        // Test7:传入内容为一个空格的字符串
[TestMethod]
public void ReplaceBlankTest7()
{
// " "
target[] = ' '; Program.ReplaceBlank(target, maxLength);
string compared = new string(this.GenerateNewTarget());
string expected = "%20"; Assert.AreEqual(compared, expected);
}

  (8)Test8:传入的字符串没有空格

        // Test8:传入的字符串没有空格
[TestMethod]
public void ReplaceBlankTest8()
{
// "helloworld "
target[] = 'h';
target[] = 'e';
target[] = 'l';
target[] = 'l';
target[] = 'o';
target[] = 'w';
target[] = 'o';
target[] = 'r';
target[] = 'l';
target[] = 'd'; Program.ReplaceBlank(target, maxLength);
string compared = new string(this.GenerateNewTarget());
string expected = "helloworld"; Assert.AreEqual(compared, expected);
}

  (9)Test9:传入的字符串全是空格

        // Test9:传入的字符串全是空格
[TestMethod]
public void ReplaceBlankTest9()
{
// " "
target[] = ' ';
target[] = ' ';
target[] = ' ';
target[] = ' ';
target[] = ' '; Program.ReplaceBlank(target, maxLength);
string compared = new string(this.GenerateNewTarget());
string expected = "%20%20%20%20%20"; Assert.AreEqual(compared, expected);
}

  单元测试结果如下图所示:

作者:周旭龙

出处:http://edisonchou.cnblogs.com

本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文链接。

剑指Offer面试题:3.替换空格的更多相关文章

  1. 剑指offer面试题4 替换空格(java)

    注:利用java中stringBuilder,append,length方法很方便的解决字符串问题 /* * 剑指offer 替换空格 * xsf * */ /*开始替换空格的函数,length为原数 ...

  2. 剑指offer面试题4 替换空格(c)

  3. 剑指Offer:面试题4——替换空格(java实现)

    问题描述:请实现一个函数,把字符串中的每个空格替换成"%20". 例如: 输入:"We are happy." 输出:"We%20are%20happ ...

  4. C++版 - 剑指offer 面试题4: 替换空格 题解

    面试题4:替换空格 提交网址: http://www.nowcoder.com/practice/4060ac7e3e404ad1a894ef3e17650423?tpId=13&tqId=1 ...

  5. 剑指Offer编程题2——替换空格

    剑指Offer编程题2——替换空格 题目描述 请实现一个函数,将一个字符串中的每个空格替换成“%20”.例如,当字符串为We Are Happy.则经过替换之后的字符串为We%20Are%20Happ ...

  6. 剑指Offer - 九度1510 - 替换空格

    剑指Offer - 九度1510 - 替换空格2013-11-29 20:53 题目描述: 请实现一个函数,将一个字符串中的空格替换成“%20”.例如,当字符串为We Are Happy.则经过替换之 ...

  7. 剑指offer第二版-5.替换空格

    面试题5:替换空格 题目要求: 实现一个函数,把字符串中的每个空格都替换成“%20”,已知原位置后面有足够的空余位置,要求改替换过程发生在原来的位置上. 思路: 首先遍历字符串求出串中空格的数量,求出 ...

  8. 剑指offer(2)替换空格

    题目描述 请实现一个函数,将一个字符串中的空格替换成“%20”.例如,当字符串为We Are Happy.则经过替换之后的字符串为We%20Are%20Happy. 题目分析 我们如果要替换空格,两步 ...

  9. 剑指offer【02】- 替换空格(Java)

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

  10. 剑指Offer(4)——替换空格

    题目: 请实现一个函数,把字符串中的每个空格替换成"%20".例如输入“We are happy.”,则输出“We%20are%20happy.”. 思路: 如果按照顺序从前往后依 ...

随机推荐

  1. Google之Chromium浏览器源码学习——base公共通用库(一)

    Google的优秀C++开源项目繁多,其中的Chromium浏览器项目可以说是很具有代表性的,此外还包括其第三开发开源库或是自己的优秀开源库,可以根据需要抽取自己感兴趣的部分.在研究.学习该项目前的时 ...

  2. jsp include flush true

    设置flush为true,就是说,如果你的缓冲区的内容很多了,就将数据读出,以免数据泄漏,造成错误服务器端页面缓冲,大致的意思是,在将生成的HTML代码送到客户端前,先在服务器端内存中保留,因为解释J ...

  3. 多线程之信号量(By C++)

    信号量在多线程中,主要是用于线程的同步或者限制线程运行的数量. 所谓同步,当流程1运行在线程1中,流程2运行在线程2中,流程2必须在流程1结束之后才能开始执行.你会怎么做,所有就需要给出一个流程1结束 ...

  4. 基于dubbo的分布式项目实例应用

    本文主要学习dubbo服务的启动检查.集群容错.服务均衡.线程模型.直连提供者.只定阅.只注册等知识点,希望通过实例演示进一步理解和掌握这些知识点. 启动检查 Dubbo缺省会在启动消费者时检查依赖的 ...

  5. Map排序

    HashMap: 最常用的Map,它根据键的HashCode 值存储数据,根据键可以直接获取它的值,具有很快的访问速度.HashMap最多只允许一条记录的键为Null(多条会覆盖);允许多条记录的值为 ...

  6. python常用模块json、os、sys

    一.序列化 json & pickle 模块 json--用于字符串和Python数据类型间进行转换 pickle---用于python特有的类型和Python的数据类型间进行转换 json: ...

  7. 德国W家HIPP 奶粉有货播报:2014.6.25 HIPP 1+ 4盒装有货啦!

    德国W家HIPP 奶粉有货播报:2014.6.25 HIPP 1+ 4盒装有货啦!

  8. VS2013开启滚动条缩略图和双击选中高亮,效果杠杠滴!

    1.双击代码或选中代码高亮,用以下插件,反应很灵敏,我安装的是第三个 2.代码编辑器的滚动条缩略图是VS自带的,需要打开菜单----工具----选项,如下图设置: 3.VS默认的选中颜色,需要打开菜单 ...

  9. 【读书笔记】《编程珠玑》第一章之位向量&位图

    此书的叙述模式是借由一个具体问题来引出的一系列算法,数据结构等等方面的技巧性策略.共分三篇,基础,性能,应用.每篇涵盖数章,章内案例都非常切实棘手,解说也生动有趣. 自个呢也是头一次接触编程技巧类的书 ...

  10. Angular 单元格合并

    在Angular实现表格输出的话,使用ng-repeat输出信息, 使用了: ng-repeat-start ng-repeat-end ng-hide="$first" < ...