剑指offer(2)—— 替换空格

题目描述

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

解题思路

1、对于java而言其实很容易,因为可以使用String类的方法。
2、如果不使用String类的方法,那么我们需要做的就是首先遍历得到空格数量,然后由于每个空格都要替换为%20,则计算相应字符的位置变动,移到对应位置上。在这个移动过程中涉及到从前往后还是从后往前,显然从后往前的效率会高一些,因为从前往后每移一次后面的字符位置都会发生改变。

代码

1、使用String类的方法

下面这个是我首先想到的,很遗憾在我的脑子里String类的常用方法并不包括replace,就连这里的deleteCharAt和insert也是在eclipse里面str.自动跳出方法之后找出来的。

public class Solution {
    public String replaceSpace(StringBuffer str) {
    	while(str.indexOf(" ") != -1){
    		int i = str.indexOf(" ");
    		str.deleteCharAt(i);
    		str.insert(i, "%20");
    	}
    	String s = str.toString();
    	return s;
    }
}

思考一下只要str.indexOf(" ")不为-1,那么就是字符串中依旧存在空格,则需要进行替换。
刚开始的时候,代码是这样的 (错误代码,未全部通过):

public String replaceSpace(StringBuffer str) {
    	int lastSpace = str.lastIndexOf(" ");
    	while(str.indexOf(" ") <= lastSpace){
    		if(str.indexOf(" ") == -1)
    			break;
    		int i = str.indexOf(" ");
    		str.deleteCharAt(i);
    		str.insert(i, "%20");
    	}
    	String s = str.toString();
    	return s;
    }

首先在这种方法中必须的判断str.indexOf(" “)是否为-1,(即找不到空格时),如果是则break,因为当为-1时还是可以进到while里面的,这时再delete就会数组越界。当然直接把不为-1设置为循环条件也可以。
然后我也是好心…用一个变量值去接收str.lastIndexOf(” “),但是忽略了其实当替换为了%20之后str.lastIndexOf(” “)是一直在变大的,因此当空格个数不止一个时是无法替换完全的。因此循环条件至少应该是while(str.indexOf(” “) <= str.lastIndexOf(” “))。
这个时候再思考一下循环条件,其实根本不需要判断是不是小于str.lastIndexOf(” "),因为当没有空格的时候就会返回-1,所以就做出了修改。

接下来我们再看一下直接用replace方法的写法:

public class Solution {
    public String replaceSpace(StringBuffer str) {
    	int index = -1;
    	while((index=str.indexOf(" ")) != -1){
    		str.replace(index, index+1, "%20");
    	}
    	String s = str.toString();
    	return s;
    }
}

2、纯手工编写

public class Solution {
    public String replaceSpace(StringBuffer str) {
    	int spaceNum = 0;
    	int len = str.length();//由于后面要改变长度,改变长度后又要用现在的长度作为循环条件,所以需存下来
    	for(int i = 0;i < len;i++){
    		if(str.charAt(i) == ' ')
    			spaceNum++;
    	}
    	//不setLength则会下标越界
    	str.setLength(str.length()+spaceNum*2);
    	
    	for(int i = len-1;i >= 0;i--){
    		if(spaceNum == 0)
    			break;
    		if(str.charAt(i) != ' ')
    		{
    			str.setCharAt(i+spaceNum*2, str.charAt(i));
    		}else{
    			spaceNum--;
    			str.setCharAt(i+spaceNum*2, '%');
    			str.setCharAt(i+spaceNum*2+1, '2');
    			str.setCharAt(i+spaceNum*2+2, '0');
    		}	
    	}
    	String s = str.toString();
    	return s;
    }
}

思路在前面已经讲过了,但是在这里我之前也犯过一些错误,比如没有重新setLength导致了下标越界,set之后发现下标还是越界,因为后面循环的时候限制条件是str.length()-1,而此时的length已经变长了,在下面加上spaceNum当然就越界了。所以要先把原来的长度存下来。
在循环中一旦if(spaceNum == 0)就break可以稍微快一点,因为第一个空格前面的字符不需要移动。

开始写的是这样的:(错误代码

public String replaceSpace(StringBuffer str) {
    	int spaceNum = 0;
    	for(int i = 0;i < str.length();i++){
    		if(str.charAt(i) == ' ')
    			spaceNum++;
    	}    	
    	for(int i = str.length()-1;i >= 0;i--){
    		if(str.charAt(i) != ' ')
    		{
    			str.setCharAt(i+spaceNum*2, str.charAt(i));
    		}else{
    			str.setCharAt(i, '%');
    			str.setCharAt(i+1, '2');
    			str.setCharAt(i+2, '0');
    			spaceNum--;
    		}	
    	}
    	String s = str.toString();
    	return s;
    }

除了上面提到的下标越界问题之外,还有一个问题,就是对空格的处理,除了第一个空格之外肯定不是i,i+1和i+2呀,但是会比它后面的少后移两个字符,因此先space–就可以了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值