题目描述
请实现一个函数,将一个字符串中的每个空格替换成“%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–就可以了。