题目:
请实现一个函数,把字符串中的每个空格替换成“%20”。例如,输入“We are happy.”,则输出“We%20are%20happy.”。
分析:
在网络编程中,如果URL参数中包含特殊字符,如空格、‘#’等,可能导致服务端无法获取正确的参数值,于是我们需要将这些特殊符号转换成服务端可以识别的字符。转换规则是在‘%’后跟上ASCII码的两位十六进制的表示。比如空格的ASCII码是32,十六进制是0x20,所以空格被替换成了“%20”。
如果我们在原字符串上进行替换,原来的一个空格字符,变成了现在的%20则3个字符,直接替换会导致后面的字符被覆盖,除非赋值前将后面内容后移两位,并且保证字符串后面有足够的空间。
以题目举的例子“We are happy.”为例,里面有两个空格,在处理第一个空格的时候,“are happy.”后移两个位置,在处理第二个空格的时候,“happy.”后移两个位置,我们发现“happy.”后移了两次。
假设,我们要处理的字符串有更多的空格呢?那么最后一部分是不是要移动很多次,我们知道,移动字符的位置是一个耗时操作,我们有没有办法一次就将最后的字符串移动到最终位置呢?也就是一开始就想法办法确定出来要移动的位置,这样就可以减少移动次数,节省时间。
再看“We are happy.”,可以统计出这个字符串有两个空格,替换前,字符串长度是14,替换后,字符串长度是18。于是,我们可以一次把“happy.”的位置确定好,也就直接后移4个位置,在把“are”的位置确定好,也就是直接后移2个位置,最后“We”的位置可以不动。
我们采用从后向前复制替换的方式。准备两个指针:p1和p2。p1指向原始字符串的末尾,p2指向替换后字符串的末尾。p1前移,并把字符依次复制给p2的位置,p2前移,直到碰到第一个空格为止。碰到第一个空格,p1前移一个位置,在p2之前插入“%20”,并把p2前移3个位置,继续向前复制,直到碰到第二个空格,以此类推。直到p1和p2指向同一个位置,说明此时所有空格都被替换完成了。
解法:
package com.wsy;
public class Main {
public static void main(String[] args) {
char[] string = "We are happy.".toCharArray();
char[] replaceString = replaceBlank(string);
System.out.println(replaceString);
}
public static char[] replaceBlank(char[] string) {
if (string == null || string.length <= 0) {
return null;
}
int blankCount = 0;
for (char c : string) {
if (c == ' ') {
blankCount++;
}
}
int originalLength = string.length;
int newLength = originalLength + blankCount * 2;
char[] replaceString = new char[newLength];
int indexOfOriginal = originalLength - 1;
int indexOfNew = newLength - 1;
while (indexOfOriginal >= 0) {
if (string[indexOfOriginal] == ' ') {
replaceString[indexOfNew--] = '0';
replaceString[indexOfNew--] = '2';
replaceString[indexOfNew--] = '%';
} else {
replaceString[indexOfNew--] = string[indexOfOriginal];
}
indexOfOriginal--;
}
return replaceString;
}
}
在Java里面,是有String类的,我们可以使用String类的replace方法来替换,也就不用写这个方法了,上面的代码是考虑到有些计算机语言中没有String,只有char的解决方案。
String s = "We are happy.";
System.out.println(s.replace(" ", "%20"));