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

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

时间复杂度为O(n2)不足以拿到Offer

现在我们考虑怎么做替换操作。最直观的做法是从头到尾扫描字符串,每一次碰到空格字符的时候做替换。由于是把1个字符替换成3个字符,我们必须把空格后面的所有的字符都后移两个字节,否则就有两个字符被覆盖了。

举个例子,我们从头到尾把“We are happy”中的每一个空格替换成”%20“。为了形象起见,我们可以用一个表格来表示字符串,表格中的每个格子表示一个字符。如下图所示:

我们替换了第一个空格,这个字符串变成图b中的内容,表格中灰色背景表示需要移动的字符。接着我们替换第二个空格,替换之后的内容如图c所示。同时我们注意到用深灰色的背景标注”happy“部分被移动了两次。

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

当我们把这种思路阐述给面试官后,他不会就此满意,他将让我们寻找更快的方法。在前面的分析中,我们发现数组中的很多字符都移动了很多次,能不能减少移动的次数呢?我们换一种思路,把从前向后替换变为从后向前替换。

考虑时间复杂度为O(n)的解法,搞定Offer就靠它了

我们先遍历一次字符串,这样就能够统计出字符串中空格的总数,并可以计算出替换之后字符串的总长度。每替换一个空格,长度增加2,因此替换以后的字符串的长度等于原来的长度加上2乘以空格的数目,我们还是以前面的字符串”We are happy”为例,“We are happy”这个字符串的长度是14,里面有两个空格,因此替换之后的字符串的长度为18

我们从字符串的后面开始复制和替换。首先准备两个指针,P1和P2.   P1指向原始字符串的末尾,而P2指向替换之后的字符串的末尾。接下来我们向前移动指针P1,逐个把它指向的字符复制到P2指向的位置,直到碰到第一个空格为止。此时字符串包含如下图b所示,灰色阴影的区域是做了字符拷贝的区域。碰到第一个空格之后,把P1向前移动一格,在P2之前插入字符串”%20“,由于”%20“的长度为3,同时也要把P2向前移动3格如图所示。

我们接着向前复制,直到碰到第二个空格(d)所示。和上一次一样,我们再把P1向前移动1格,并把P2向前移动3格插入”%20“(如图e),此时P1,P2指向同一个位置,表明所有的空格都已经替换完毕。

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

实现如下:(我的指针是从前面开始的)

public class Test4 {

    //将字符串中的空格变成%20
public static String replaceAll(String str){
//计算有多少个空格
int count=0;
char[] strArr = str.toCharArray();
for(int i=0;i<strArr.length;i++){
if(strArr[i]==' '){
count++;
}
}
//定义新数组
char[] newArr=new char[strArr.length+count*2];
//遍历原数组,碰见空格就在新数组中写入'%''2''0'
//第几个空格
int num=0;
for(int i=0,j=0;i<strArr.length;i++){
//定义一个变量来存newArr的索引
if(strArr[i]!=' '){
newArr[j++]=strArr[i];
}else{
newArr[j++]='%';
newArr[j++]='2';
newArr[j++]='0';
}
} return new String(newArr);
} public static void main(String[] args) {
String str = replaceAll("hello world nihao a");
System.out.println(str);
}
}

剑指offer第二版面试题4:替换空格(JAVA版)的更多相关文章

  1. 《剑指offer》面试题4 替换空格 Java版

    (给一个足够长的字符数组,其中有一段字符,将' '(空格)替换成'%' '2' '0'三个字符,原字符段由'\0'结尾) 书中方法:这道题如果从头到尾扫描数组并替换,会涉及到数组的移动.如果不移动元素 ...

  2. 【剑指offer】面试题 5. 替换空格

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

  3. 剑指offer第二版面试题6:重建二叉树(JAVA版)

    题目:输入某二叉树的前序遍历和中序遍历的结果,请重新构造出该二叉树.假设输入的前序遍历和中序遍历的结果中不包含重复的数字.例如输入的前序遍历序列为{1,2,4,7,3,5,6,8}和中序遍历为{4,7 ...

  4. 剑指offer第二版面试题5:从尾到头打印链表(JAVA版)

    题目描述: 输入一个链表,从尾到头打印链表每个节点的值.返回新链表. import java.util.Stack; //定义链表结构 class ListNode { int value; List ...

  5. 剑指offer第二版面试题11:旋转数组的最小数字(JAVA版)

    题目:把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转.输入一个递增排序的数组的一个旋转,输出旋转数组的最小元素.例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数 ...

  6. 剑指offer第二版面试题10:斐波那契数列(JAVA版)

    题目:写一个函数,输入n,求斐波那契数列的第n项.斐波那契数列的定义如下: 1.效率很低效的解法,挑剔的面试官不会喜欢 使用递归实现: public class Fibonacci { public ...

  7. 剑指offer第二版面试题9:用两个队列实现栈(JAVA版)

    题目:用两个队列实现栈. 分析:通过一系列的栈的压入和弹出操作来分析用队列模拟一个栈的过程,如图所示,我们先往栈内压入一个元素a.由于两个队列现在都是空,我们可以选择把a插入两个队列中的任一个.我们不 ...

  8. 剑指offer第二版面试题8:用两个栈实现队列(JAVA版)

    题目:用两个栈实现一个队列.队列的声明如下,请实现它的两个函数appendTail和deletedHead,分别完成在队列尾部插入节点和在队列头部删除节点的功能. 分析: 我们通过一个具体的例子来分析 ...

  9. 剑指offer第二版面试题7:二叉树的下一个节点(JAVA版本)

    题目:给定一个二叉树和其中的一个结点,请找出中序遍历顺序的下一个结点并且返回.注意,树中的结点不仅包含左右子结点,同时包含指向父结点的指针. 分析: 根据中序遍历的特点,要找到一个节点的下一个节点无非 ...

随机推荐

  1. USB编程概念

     RE:USB编程概念 >请你指导我如何学习USB虚拟COM端口PROGRAMM,什么是我们needto有(如硬件和软件)的东西. USB是一个典型的复杂的协议栈,在协议的协议.这是很难完全实现 ...

  2. sqlserver2012分页注意事项

    SELECT orderid, orderdate, custid, empid FROM Sales.Orders ORDER BY orderdate, orderid OFFSET 600 RO ...

  3. Java学习之面向对象---继承

    继承:子继承父,子可以拥有父的所有. 继承的好处: 1.提高了代码的复用性 2.让类与类之间产生了关系.有了这个关系,才有了多态的特性 Java 只支持单继承,不支持多继承 class A { voi ...

  4. javsscript闭包的一种使用场景--沙箱

    ​ //沙箱:模块化,沙箱是一个隔离的环境,最大的好处就是避免全局变量的污染. var model = (function () {//一个匿名的立即执行函数 var price = 900;//这是 ...

  5. python中输入多个数字(代码实现)

    不多说,直接上代码: list1 = [] #定义一个空列表 str1 = input("请输入数值,用空格隔开:") # list2 = str1.split(" &q ...

  6. 程序性能优化之APK大小优化(六)上

    阿里P7移动互联网架构师进阶视频(每日更新中)免费学习请点击:https://space.bilibili.com/474380680 本篇文章将继续从APK瘦身来介绍APK大小优化:文章主要内容从理 ...

  7. springboot Service层单元测试

    两个实现类实现同一个Service接口 public interface CustomUrlService { List<ShopMetrics> getShopMetrics(); } ...

  8. go的目录规范

    这里举一个简单的例子:如果我们在建立一个goProject目录,通常在这个目录下我们会创建如下目录 src 存放不同的项目代码 bin 存放编译后的可执行程序 vender 存放引用的第三方库 pgk ...

  9. jq 将translate的旋转角度转为数值

    // 将translate内的角度转为数值 function getmatrix(nowDeg){ var values = nowDeg.split('(')[1].split(')')[0].sp ...

  10. python re.I compile search

    import restring = "The quick brown fox jumps over the lazy dog."a_list = string.split()pat ...