一、题目:替换空格
题目:请实现一个函数,把字符串中的每个空格替换成"%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),比第一个思路要快。
三、代码实现
方法一:
package stringTest;
public class RemoveBlank {
public static String replaceBlank(char[] string) {
if (string == null ){
return null;
}
// originalLength 为字符串length的实际长度
int originalLength = string.length;
int blankCount = 0;
//计算空格数
for(int i=0;i<originalLength;i++){
if(string[i]==' ') {
blankCount++;
}
}
// newLength 为把空格替换成'%20'之后的长度
int newLength = originalLength + 2 * blankCount;
char[] temp=new char[newLength];
/*
if (newLength > temp.length)
{
return null;
}
*/
// 设置两个下标,一个指向原始字符串的末尾,另一个指向替换之后的字符串的末尾
int indexOfOriginal = originalLength-1;
int indexOfNew = newLength-1;
while (indexOfOriginal >= 0 && indexOfNew >=indexOfOriginal){
if (string[indexOfOriginal] == ' '){
temp[indexOfNew--] = '0';
temp[indexOfNew--] = '2';
temp[indexOfNew--] = '%';
}
else{
temp[indexOfNew--] = string[indexOfOriginal];
}
indexOfOriginal--;
}
return new String(temp);//将字符数组转换成字符串
}
public static void main(String[] args) {
String string=" We are happy. ";
/*System.out.println(string.toCharArray());
for(int i=0;i<string.length();i++) {
System.out.print(string.charAt(i)+"-");
}*/
System.out.println(replaceBlank(string.toCharArray()));
}
}
方法二:
public static String replaceBlank(StringBuffer str) {
int length = str.length();
int blankCount = 0;
//统计空格字符个数
for(int i=0;i<length;i++){
if(str.charAt(i) == ' ')
blankCount++;
}
int lengthNew = length + blankCount*2;
str.setLength(lengthNew);
int indexOfOriginal = length-1;
int indexOfNew = lengthNew-1;
for(;indexOfOriginal>=0;indexOfOriginal--){
if(str.charAt(indexOfOriginal) == ' '){
str.setCharAt(indexOfNew--, '0');
str.setCharAt(indexOfNew--, '2');
str.setCharAt(indexOfNew--, '%');
}
else{
str.setCharAt(indexOfNew--, str.charAt(indexOfOriginal));
}
}
return str.toString();
}